source: release/1.7/source/lisp-kernel/x86-spentry32.s @ 15267

Last change on this file since 15267 was 14657, checked in by rme, 8 years ago

Don't bother to save/restore the state of the direction flag in
SPffcall and friends.

We already assume that the registers are in their normal state (we
push all the default node registers onto the lisp stack), so it's
just pointless.

File size: 155.5 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        __(emms)
1056        __(pop %ebp)            /* backlink */
1057        __(lea 15(%esp),%edx)
1058        __(andl $-16,%edx)
1059        __(movl %edx,%esp)
1060        __(unbox_fixnum(%arg_z,%eax))   /* syscall number */
1061        __(movl $local_label(back_from_sysenter),%edx)
1062        __(push %edx)
1063        __(movl %esp,%ecx)
1064        __(sysenter)
1065local_label(back_from_sysenter):
1066        __(jnc 0f)
1067        __(neg %eax)
10680:     
1069        __(movl %ebp,%esp)
1070        __(movl %esp,rcontext(tcr.foreign_sp))
1071        __(clr %arg_z)
1072        __(clr %arg_y)
1073        __(clr %temp1)
1074        __(clr %temp0)
1075        __(clr %fn)
1076        __(pxor %fpzero,%fpzero)
1077        __(movl rcontext(tcr.save_vsp),%esp)
1078        __(movl rcontext(tcr.save_ebp),%ebp)
1079        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
1080        __(pop %fn)
1081        __(pop %arg_z)
1082        __(pop %arg_y)
1083        __(pop %temp1)
1084        __(check_pending_interrupt(%temp0))
1085        __(pop %temp0)
1086        __(leave)
1087        __(ret)
1088_endsubp(syscall)
1089
1090/* Make system call that returns a doubleword result in %edx:%eax and */
1091/* copy the result into %mm0. */
1092_spentry(syscall2)
1093        /* Save lisp registers */
1094        __(push %ebp)
1095        __(movl %esp,%ebp)
1096        __(push %temp0)
1097        __(push %temp1)
1098        __(push %arg_y)
1099        __(push %arg_z)
1100        __(push %fn)
1101        __(movl %esp,rcontext(tcr.save_vsp))
1102        __(movl %ebp,rcontext(tcr.save_ebp))
1103        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
1104        __(movl rcontext(tcr.foreign_sp),%esp)
1105        __(emms)
1106        __(pop %ebp)            /* backlink */
1107        __(lea 15(%esp),%edx)
1108        __(andl $-16,%edx)
1109        __(movl %edx,%esp)
1110        __(unbox_fixnum(%arg_z,%eax))   /* syscall number */
1111        __(pushl $local_label(back_from_syscall))
1112        __(int $0x80)
1113local_label(back_from_syscall):
1114        __(jnc 0f)
1115        __(neg %eax)
1116        __(movl $-1,%edx)
11170:
1118        /* just use memory rather than screwing around with */
1119        /* movd %eax,%mm0, movd %edx,%mm1, psllq $32,%mm1, por %mm1,%mm0 */
1120        __(push %edx)
1121        __(push %eax)
1122        __(movq (%esp),%mm0)
1123        __(movl %ebp,%esp)
1124        __(movl %esp,rcontext(tcr.foreign_sp))
1125        __(clr %arg_z)
1126        __(clr %arg_y)
1127        __(clr %temp1)
1128        __(clr %temp0)
1129        __(clr %fn)
1130        __(pxor %fpzero,%fpzero)
1131        __(movl rcontext(tcr.save_vsp),%esp)
1132        __(movl rcontext(tcr.save_ebp),%ebp)
1133        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
1134        __(pop %fn)
1135        __(pop %arg_z)
1136        __(pop %arg_y)
1137        __(pop %temp1)
1138        __(check_pending_interrupt(%temp0))
1139        __(pop %temp0)
1140        __(leave)
1141        __(ret)
1142_endsubp(syscall2)
1143
1144
1145_spentry(mkcatch1v)
1146        __(nMake_Catch(0))
1147        __(ret)
1148_endsubp(mkcatch1v)
1149
1150_spentry(mkunwind)
1151        __(movl $undefined,%arg_z)
1152        __(Make_Catch(fixnumone))
1153        __(jmp *%ra0)
1154_endsubp(mkunwind)
1155
1156/* this takes a return address in %ra0; it's "new" in that it does the */
1157/*   double binding of *interrupt-level* out-of-line */
1158_spentry(nmkunwind)
1159        __(movl rcontext(tcr.tlb_pointer),%arg_z)
1160        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_z),%arg_y)
1161        __(push %arg_y)
1162        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
1163        __(push rcontext(tcr.db_link))
1164        __(movl %esp,rcontext(tcr.db_link))
1165        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_z))
1166        __(movl $undefined,%arg_z)
1167        /* %arg_z = tag, %xfn (%temp1) = pc */
1168        __(Make_Catch(fixnumone))
1169        __(movl %arg_y,%arg_z)
1170        __(jmp _SPbind_interrupt_level)
1171_endsubp(nmkunwind)
1172
1173_spentry(mkcatchmv)
1174        __(nMake_Catch(fixnumone))
1175        __(ret)
1176_endsubp(mkcatchmv)
1177
1178_spentry(throw)
1179        __(movl rcontext(tcr.catch_top),%imm0)
1180        __(movl (%esp,%nargs),%arg_y)   /* arg_y = tag   */
1181        __(movd %nargs,%mm0)
1182        __(xorl %temp1,%temp1)
1183        __(jmp local_label(_throw_test))
1184local_label(_throw_loop):
1185        __(cmpl %arg_y,catch_frame.catch_tag(%imm0))
1186        __(je local_label(_throw_found))
1187        __(movl catch_frame.link(%imm0),%imm0)
1188        __(addl $fixnum_one,%temp1)
1189local_label(_throw_test):
1190        __(test %imm0,%imm0)
1191        __(jne local_label(_throw_loop))
1192        __(push %ra0)
1193        __(uuo_error_reg_not_tag(Rarg_y,subtag_catch_frame))
1194        __(pop %ra0)
1195        __(jmp _SPthrow)
1196local_label(_throw_found):
1197        __(testb $fulltagmask,catch_frame.mvflag(%imm0))
1198        __(movl %temp1,%imm0)
1199        __(movd %mm0,%nargs)
1200        __(jne local_label(_throw_multiple))
1201        __(movl $nil_value,%arg_z)
1202        __(test %nargs,%nargs)
1203        __(je local_label(_throw_one_value))
1204        __(movl -node_size(%esp,%nargs),%arg_z)
1205        __(add %nargs,%esp)
1206local_label(_throw_one_value):
1207        __(movl $local_label(_threw_one_value),%ra0)
1208        __(jmp _SPnthrow1value)
1209__(tra(local_label(_threw_one_value)))
1210        __(movl rcontext(tcr.catch_top),%arg_y)
1211        __(movl catch_frame.db_link(%arg_y),%imm0)
1212        __(cmpl %imm0,rcontext(tcr.db_link))
1213        __(jz local_label(_threw_one_value_dont_unbind))
1214        __(push $local_label(_threw_one_value_dont_unbind))
1215        __(jmp _SPunbind_to)    /* preserves registers */
1216__(tra(local_label(_threw_one_value_dont_unbind)))
1217        __(movl catch_frame.ebp(%arg_y),%ebp)
1218        __(movl catch_frame.foreign_sp(%arg_y),%imm0)
1219        __(movl %imm0,rcontext(tcr.foreign_sp))
1220        __(movl catch_frame.xframe(%arg_y),%imm0)
1221        __(movl %imm0,rcontext(tcr.xframe))
1222        __(movl catch_frame.esp(%arg_y),%esp)
1223        __(movl catch_frame.link(%arg_y),%imm0)
1224        __(movl %imm0,rcontext(tcr.catch_top))
1225        __(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
1226        __(movl (%imm0),%imm0)
1227        __(movl %imm0,rcontext(tcr.save_tsp))
1228        __(movl %imm0,rcontext(tcr.next_tsp))
1229        __(movl catch_frame.pc(%arg_y),%ra0)
1230        __(jmp *%ra0)
1231local_label(_throw_multiple):
1232        __(movl $local_label(_threw_multiple),%ra0)
1233        __(jmp _SPnthrowvalues)
1234__(tra(local_label(_threw_multiple)))
1235        __(movl rcontext(tcr.catch_top),%arg_y)
1236        __(movl catch_frame.db_link(%arg_y),%imm0)
1237        __(cmpl %imm0,rcontext(tcr.db_link))
1238        __(je local_label(_threw_multiple_dont_unbind))
1239        __(push $local_label(_threw_multiple_dont_unbind))
1240        __(jmp _SPunbind_to)    /* preserves registers */
1241__(tra(local_label(_threw_multiple_dont_unbind)))
1242        /* Copy multiple values from the current %esp to the target %esp   */
1243        __(lea (%esp,%nargs),%imm0)
1244        __(movd %nargs,%mm0)    /* nargs is aka temp1 */
1245        __(movl catch_frame.esp(%arg_y),%temp1)
1246        __(jmp local_label(_threw_multiple_push_test))
1247local_label(_threw_multiple_push_loop):
1248        __(subl $node_size,%imm0)
1249        __(subl $node_size,%temp1)
1250        __(movl (%imm0),%arg_z)
1251        __(movl %arg_z,(%temp1))
1252local_label(_threw_multiple_push_test):
1253        __(cmpl %imm0,%esp)
1254        __(jne local_label(_threw_multiple_push_loop))
1255        /* target %esp is now in %temp1   */
1256        __(movl catch_frame.ebp(%arg_y),%ebp)
1257        __(movl catch_frame.foreign_sp(%arg_y),%imm0)
1258        __(movl %imm0,rcontext(tcr.foreign_sp))       
1259        __(movl catch_frame.xframe(%arg_y),%imm0)
1260        __(movl %imm0,rcontext(tcr.xframe))
1261        __(movl %temp1,%esp)
1262        __(movl catch_frame.link(%arg_y),%temp1)
1263        __(movl %temp1,rcontext(tcr.catch_top))
1264        __(movd %mm0,%nargs)
1265        __(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
1266        __(movl catch_frame.pc(%arg_y),%ra0)
1267        __(movl (%imm0),%imm0)
1268        __(movl %imm0,rcontext(tcr.save_tsp))
1269        __(movl %imm0,rcontext(tcr.next_tsp))
1270        __(jmp *%ra0)
1271_endsubp(throw)
1272
1273        /* This takes N multiple values atop the vstack.   */
1274_spentry(nthrowvalues)
1275        __(movb $1,rcontext(tcr.unwinding))
1276        __(movl %ra0,rcontext(tcr.save0)) /* %ra0 (aka %temp0) to spill area */
1277local_label(_nthrowv_nextframe):
1278        __(subl $fixnumone,%imm0)
1279        __(js local_label(_nthrowv_done))
1280        __(movd %imm0,%mm1)
1281        __(movl rcontext(tcr.catch_top),%temp0)
1282        __(movl catch_frame.link(%temp0),%imm0)
1283        __(movl %imm0,rcontext(tcr.catch_top))
1284        __(movl catch_frame.db_link(%temp0),%imm0)
1285        __(cmpl %imm0,rcontext(tcr.db_link))
1286        __(jz local_label(_nthrowv_dont_unbind))
1287        __(push %temp1)
1288        __(push %temp0)
1289        __(push $local_label(_nthrowv_back_from_unbind))
1290        __(jmp _SPunbind_to)
1291__(tra(local_label(_nthrowv_back_from_unbind)))
1292        __(pop %temp0)
1293        __(pop %temp1)
1294local_label(_nthrowv_dont_unbind):
1295        __(cmpb $unbound_marker,catch_frame.catch_tag(%temp0))
1296        __(je local_label(_nthrowv_do_unwind))
1297/* A catch frame.  If the last one, restore context from there.   */
1298        __(movd %mm1,%imm0)
1299        __(test %imm0,%imm0)    /* last catch frame ?   */
1300        __(jne local_label(_nthrowv_skip))
1301        __(movl catch_frame.xframe(%temp0),%arg_y)
1302        __(movl %arg_y,rcontext(tcr.xframe))
1303        __(lea (%esp,%nargs),%arg_y)
1304        __(movl catch_frame.esp(%temp0),%arg_z)
1305        __(movd %nargs,%mm2)
1306        __(jmp local_label(_nthrowv_push_test))
1307local_label(_nthrowv_push_loop):
1308        __(subl $node_size,%arg_y)
1309        __(subl $node_size,%arg_z)
1310        __(movd (%arg_y),%mm0)
1311        __(movd %mm0,(%arg_z))
1312local_label(_nthrowv_push_test):
1313        __(subl $node_size,%nargs)
1314        __(jns local_label(_nthrowv_push_loop))
1315        __(movd %mm2,%nargs)
1316        __(movl catch_frame.xframe(%temp0),%arg_y)
1317        __(movl %arg_y,rcontext(tcr.xframe))
1318        __(movl %arg_z,%esp)
1319        __(movl catch_frame.ebp(%temp0),%ebp)
1320        __(movd catch_frame.foreign_sp(%temp0),%stack_temp)
1321        __(movd %stack_temp,rcontext(tcr.foreign_sp))       
1322local_label(_nthrowv_skip):     
1323        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
1324        __(movl %imm0,rcontext(tcr.save_tsp))
1325        __(movl %imm0,rcontext(tcr.next_tsp))
1326        __(movd %mm1,%imm0)
1327        __(jmp local_label(_nthrowv_nextframe))
1328local_label(_nthrowv_do_unwind):       
1329/* This is harder.  Call the cleanup code with the multiple values and   */
1330/* nargs, the throw count, and the caller's return address in a temp  */
1331/* stack frame.   */
1332        __(leal (%esp,%nargs),%arg_y)
1333        __(push catch_frame.pc(%temp0))
1334        __(movl catch_frame.ebp(%temp0),%ebp)
1335        __(movd catch_frame.xframe(%temp0),%stack_temp)
1336        __(movd %stack_temp,rcontext(tcr.xframe))
1337        __(movl catch_frame.esp(%temp0),%arg_z)
1338        __(movd catch_frame.foreign_sp(%temp0),%stack_temp)
1339        __(movd %stack_temp,rcontext(tcr.foreign_sp))       
1340        /* Discard the catch frame, so we can build a temp frame   */
1341        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
1342        __(movl %imm0,rcontext(tcr.save_tsp))
1343        __(movl %imm0,rcontext(tcr.next_tsp))
1344        __(movd %temp1,%mm2) /* save %nargs */
1345        /* tsp overhead, nargs, throw count, ra0   */
1346        __(dnode_align(%nargs,(tsp_frame.fixed_overhead+(3*node_size)),%imm0))
1347        __(movl %imm0,%temp1)
1348        __(TSP_Alloc_Var(%temp1,%imm0))
1349        __(movd %mm2,%temp1) /* aka %nargs */
1350
1351        __(movl %nargs,(%imm0))
1352        __(movl rcontext(tcr.save0),%ra0)
1353        __(movl %ra0,node_size(%imm0))
1354        __(movd %mm1,node_size*2(%imm0))
1355        __(leal node_size*3(%imm0),%imm0)
1356        __(jmp local_label(_nthrowv_tpushtest))
1357local_label(_nthrowv_tpushloop):
1358        __(movl -node_size(%arg_y),%temp0)
1359        __(subl $node_size,%arg_y)
1360        __(movl %temp0,(%imm0))
1361        __(addl $node_size,%imm0)
1362local_label(_nthrowv_tpushtest):
1363        __(subl $node_size,%nargs)
1364        __(jns local_label(_nthrowv_tpushloop))
1365        __(pop %xfn)    /* aka %temp1/%nargs */
1366        __(movl %arg_z,%esp)
1367/* Ready to call cleanup code. set up tra, jmp to %xfn   */
1368        __(push $local_label(_nthrowv_called_cleanup))
1369        __(movb $0,rcontext(tcr.unwinding))
1370        __(jmp *%xfn)
1371__(tra(local_label(_nthrowv_called_cleanup)))
1372
1373        __(movb $1,rcontext(tcr.unwinding))
1374        __(movl rcontext(tcr.save_tsp),%imm0)
1375        __(movl tsp_frame.data_offset+(0*node_size)(%imm0),%nargs)
1376        __(movl tsp_frame.data_offset+(1*node_size)(%imm0),%ra0)
1377        __(movl %ra0,rcontext(tcr.save0))
1378        __(movd tsp_frame.data_offset+(2*node_size)(%imm0),%mm1)
1379        __(movd %nargs,%mm2)
1380        __(addl $tsp_frame.fixed_overhead+(node_size*3),%imm0)
1381        __(jmp local_label(_nthrowv_tpoptest))
1382local_label(_nthrowv_tpoploop):
1383        __(push (%imm0))
1384        __(addl $node_size,%imm0)
1385local_label(_nthrowv_tpoptest):
1386        __(subl $node_size,%nargs)
1387        __(jns local_label(_nthrowv_tpoploop))
1388        __(movd %mm2,%nargs)
1389        __(movl rcontext(tcr.save_tsp),%imm0)
1390        __(movl (%imm0),%imm0)
1391        __(movl %imm0,rcontext(tcr.save_tsp))
1392        __(movl %imm0,rcontext(tcr.next_tsp))
1393        __(movd %mm1,%imm0)
1394        __(jmp local_label(_nthrowv_nextframe))
1395local_label(_nthrowv_done):
1396        __(movb $0,rcontext(tcr.unwinding))
1397        __(check_pending_interrupt(%imm0))
1398local_label(_nthrowv_return):
1399        __(movl rcontext(tcr.save0),%ra0)
1400        __(movss %fpzero,rcontext(tcr.save0))
1401        __(jmp *%ra0)   
1402_endsubp(nthrowvalues)
1403
1404/* This is a (slight) optimization.  When running an unwind-protect,  */
1405/* save the single value and the throw count in the tstack frame.  */
1406/* Note that this takes a single value in arg_z.  */
1407
1408_spentry(nthrow1value)
1409        __(movb $1,rcontext(tcr.unwinding))
1410local_label(_nthrow1v_nextframe):
1411        __(subl $fixnumone,%imm0)
1412        __(js local_label(_nthrow1v_done))
1413        __(movd %imm0,%mm0)
1414        __(movl rcontext(tcr.catch_top),%temp1)
1415        __(movl catch_frame.link(%temp1),%imm0)
1416        __(movl %imm0,rcontext(tcr.catch_top))
1417        __(movl catch_frame.db_link(%temp1),%imm0)
1418        __(cmpl %imm0,rcontext(tcr.db_link))
1419        __(jz local_label(_nthrow1v_dont_unbind))
1420        __(push %temp1)
1421        __(push %temp0)
1422        __(push %arg_z)
1423        __(push `$'local_label(_nthrow1v_back_from_unbind))
1424        __(jmp _SPunbind_to)
1425__(tra(local_label(_nthrow1v_back_from_unbind)))
1426        __(pop %arg_z)
1427        __(pop %temp0)
1428        __(pop %temp1)
1429local_label(_nthrow1v_dont_unbind):
1430        __(cmpb $unbound_marker,catch_frame.catch_tag(%temp1))
1431        __(je local_label(_nthrow1v_do_unwind))
1432/* A catch frame.  If the last one, restore context from there. */
1433        __(movd %mm0,%imm0)
1434        __(test %imm0,%imm0)    /* last catch frame? */
1435        __(jne local_label(_nthrow1v_skip))
1436        __(movl catch_frame.xframe(%temp1),%arg_y)
1437        __(movl %arg_y,rcontext(tcr.xframe))
1438        __(movl catch_frame.esp(%temp1),%esp)
1439        __(movl catch_frame.ebp(%temp1),%ebp)
1440        __(movd catch_frame.foreign_sp(%temp1),%stack_temp)
1441        __(movd %stack_temp,rcontext(tcr.foreign_sp))
1442local_label(_nthrow1v_skip):
1443        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
1444        __(movl %imm0,rcontext(tcr.save_tsp))
1445        __(movl %imm0,rcontext(tcr.next_tsp))
1446        __(movd %mm0,%imm0)
1447        __(jmp local_label(_nthrow1v_nextframe))
1448local_label(_nthrow1v_do_unwind):
1449/* This is harder, but not as hard (not as much BLTing) as the */
1450/* multiple-value case. */
1451        __(movl catch_frame.xframe(%temp1),%arg_y)
1452        __(movl %arg_y,rcontext(tcr.xframe))
1453        __(movl catch_frame.ebp(%temp1),%ebp)
1454        __(movl catch_frame.esp(%temp1),%esp)
1455        __(movd catch_frame.foreign_sp(%temp1),%stack_temp)
1456        __(movd %stack_temp,rcontext(tcr.foreign_sp))
1457        /* Discard the catch frame so we can build a temp frame. */
1458        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
1459        __(movl %imm0,rcontext(tcr.save_tsp))
1460        __(movl %imm0,rcontext(tcr.next_tsp))
1461        __(movl catch_frame.pc(%temp1),%xfn) /* xfn is temp1 */
1462        __(TSP_Alloc_Fixed((3*node_size),%imm0))
1463        __(addl $tsp_frame.fixed_overhead,%imm0)
1464        __(movl %ra0,(%imm0))
1465        __(movd %mm0,node_size*1(%imm0))
1466        __(movl %arg_z,node_size*2(%imm0))
1467/* Ready to call cleanup code.  Set up tra, jmp to %xfn. */
1468        __(push $local_label(_nthrow1v_called_cleanup))
1469        __(movb $0,rcontext(tcr.unwinding))
1470        __(jmp *%xfn)
1471__(tra(local_label(_nthrow1v_called_cleanup)))
1472        __(movb $1,rcontext(tcr.unwinding))
1473        __(movl rcontext(tcr.save_tsp),%imm0)
1474        __(movl tsp_frame.data_offset+(0*node_size)(%imm0),%ra0)
1475        __(movd tsp_frame.data_offset+(1*node_size)(%imm0),%mm0)
1476        __(movl tsp_frame.data_offset+(2*node_size)(%imm0),%arg_z)
1477        __(movl (%imm0),%imm0)
1478        __(movl %imm0,rcontext(tcr.save_tsp))
1479        __(movl %imm0,rcontext(tcr.next_tsp))
1480        __(movd %mm0,%imm0)
1481        __(jmp local_label(_nthrow1v_nextframe))
1482local_label(_nthrow1v_done):
1483        __(movb $0,rcontext(tcr.unwinding))
1484        __(check_pending_interrupt(%imm0))
1485local_label(_nthrow1v_return):
1486        __(jmp *%ra0)
1487_endsubp(nthrow1value)
1488
1489/* This never affects the symbol's vcell   */
1490/* Non-null symbol in arg_y, new value in arg_z           */
1491
1492_spentry(bind)
1493        __(movl symbol.binding_index(%arg_y),%imm0)
1494        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1495        __(jb 0f)
1496        __(push %imm0)
1497        __(tlb_too_small())
14980:      __(test %imm0,%imm0)
1499        __(jz 9f)
1500        __(movl rcontext(tcr.tlb_pointer),%temp1)
1501        __(push (%temp1,%imm0))
1502        __(push %imm0)
1503        __(push rcontext(tcr.db_link))
1504        __(movl %esp,rcontext(tcr.db_link))
1505        __(movl %arg_z,(%temp1,%imm0))
1506        __(jmp *%ra0)
15079:     
1508        __(movl %arg_y,%arg_z)
1509        __(movl $XSYMNOBIND,%arg_y)
1510        __(set_nargs(2))
1511        __(push %ra0)
1512        __(jmp _SPksignalerr)
1513_endsubp(bind)
1514
1515/* arg_z = symbol: bind it to its current value  */
1516
1517_spentry(bind_self)
1518        __(movl symbol.binding_index(%arg_z),%imm0)
1519        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1520        __(jb 0f)
1521        __(push %imm0)
1522        __(tlb_too_small())
15230:      __(test %imm0,%imm0)
1524        __(jz 9f)
1525        __(movl rcontext(tcr.tlb_pointer),%temp1)
1526        __(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
1527        __(jz 2f)
1528        __(push (%temp1,%imm0))
1529        __(push %imm0)
1530        __(push rcontext(tcr.db_link))
1531        __(movl %esp,rcontext(tcr.db_link))
1532        __(jmp *%ra0)
15332:      __(movl symbol.vcell(%arg_z),%arg_y)
1534        __(push (%temp1,%imm0))
1535        __(push %imm0)
1536        __(push rcontext(tcr.db_link))
1537        __(movl %arg_y,(%temp1,%imm0))
1538        __(movl %esp,rcontext(tcr.db_link))
1539        __(jmp *%ra0)
15409:      __(movl $XSYMNOBIND,%arg_y)
1541        __(set_nargs(2))
1542        __(push %ra0)
1543        __(jmp _SPksignalerr)
1544_endsubp(bind_self)
1545
1546_spentry(bind_nil)
1547        __(movl symbol.binding_index(%arg_z),%imm0)
1548        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1549        __(jb 0f)
1550        __(push %imm0)
1551        __(tlb_too_small())
15520:      __(test %imm0,%imm0)
1553        __(jz 9f)
1554        __(movl rcontext(tcr.tlb_pointer),%temp1)
1555        __(push (%temp1,%imm0))
1556        __(push %imm0)
1557        __(push rcontext(tcr.db_link))
1558        __(movl %esp,rcontext(tcr.db_link))
1559        __(movl $nil_value,(%temp1,%imm0))
1560        __(jmp *%ra0)
15619:      __(movl $XSYMNOBIND,%arg_y)
1562        __(set_nargs(2))
1563        __(push %ra0)
1564        __(jmp _SPksignalerr)
1565_endsubp(bind_nil)
1566
1567_spentry(bind_self_boundp_check)
1568        __(movl symbol.binding_index(%arg_z),%imm0)
1569        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1570        __(jb 0f)
1571        __(push %imm0)
1572        __(tlb_too_small())
15730:      __(test %imm0,%imm0)
1574        __(jz 9f)
1575        __(movl rcontext(tcr.tlb_pointer),%temp1)
1576        __(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
1577        __(je 2f)
1578        __(cmpb $unbound_marker,(%temp1,%imm0))
1579        __(je 8f)
1580        __(push (%temp1,%imm0))
1581        __(push %imm0)
1582        __(push rcontext(tcr.db_link))
1583        __(movl %esp,rcontext(tcr.db_link))
1584        __(jmp *%ra0)
15852:      __(movl symbol.vcell(%arg_z),%arg_y)
1586        __(cmpl $unbound_marker,%arg_y)
1587        __(jz 8f)
1588        __(push (%temp1,%imm0))
1589        __(push %imm0)
1590        __(push rcontext(tcr.db_link))
1591        __(movl %esp,rcontext(tcr.db_link))
1592        __(movl %arg_y,(%temp1,%imm0))
1593        __(jmp *%ra0)
15948:      __(push %ra0)
1595        __(uuo_error_reg_unbound(Rarg_z))
1596       
15979:      __(movl $XSYMNOBIND,%arg_y)
1598        __(set_nargs(2))
1599        __(push %ra0)
1600        __(jmp _SPksignalerr)
1601_endsubp(bind_self_boundp_check)
1602
1603_spentry(conslist)
1604        __(movl %nargs,%imm0)
1605        __(movl %temp0,%temp1)  /* have to use temp0 for consing */
1606        __(movl $nil_value,%arg_z)
1607        __(test %imm0,%imm0)
1608        __(jmp 2f)
16091:      __(pop %arg_y)
1610        __(Cons(%arg_y,%arg_z,%arg_z))
1611        __(subl $node_size,%imm0)
16122:      __(jnz 1b)
1613        __(jmp *%temp1)
1614_endsubp(conslist)
1615
1616/* do list*: last arg in arg_z, all others pushed, nargs set to #args pushed.  */
1617/* Cons, one cons cell at at time.  Maybe optimize this later.  */
1618
1619_spentry(conslist_star)
1620        __(movl %nargs,%imm0)
1621        __(test %imm0,%imm0)
1622        __(movl %ra0,%temp1)
1623        __(jmp 2f)
16241:      __(pop %arg_y)
1625        __(Cons(%arg_y,%arg_z,%arg_z))
1626        __(subl $node_size,%imm0)
16272:      __(jnz 1b)
1628        __(jmp *%temp1)
1629_endsubp(conslist_star)
1630
1631/* We always have to create a tsp frame (even if nargs is 0), so the compiler */
1632/* doesn't get confused. */
1633_spentry(stkconslist)
1634        __(movl $nil_value,%arg_z)
1635C(stkconslist_common):               
1636        __(movl %ra0,rcontext(tcr.save0))
1637        __(movd %nargs,%mm0)
1638        __(movl %nargs,%temp0)
1639        __(addl %temp0,%temp0)
1640        __(dnode_align(%temp0,tsp_frame.fixed_overhead,%temp0))
1641        __(TSP_Alloc_Var(%temp0,%imm0))
1642        __(addl $fulltag_cons,%imm0)
1643        __(test %nargs,%nargs)
1644        __(jmp 2f)
16451:      __(pop %arg_y)
1646        __(_rplaca(%imm0,%arg_y))
1647        __(_rplacd(%imm0,%arg_z))
1648        __(movl %imm0,%arg_z)
1649        __(add $cons.size,%imm0)
1650        __(subl $node_size,%nargs)
16512:      __(jne 1b)
1652        __(movl rcontext(tcr.save0),%ra0)
1653        __(movl $0,rcontext(tcr.save0))
1654        __(jmp *%ra0)
1655_endsubp(stkconslist)
1656
1657/* do list*: last arg in arg_z, all others vpushed,   */
1658/*      nargs set to #args vpushed.  */
1659
1660_spentry(stkconslist_star)
1661        __(jmp C(stkconslist_common))
1662_endsubp(stkconslist_star)
1663
1664
1665/* Make a stack-consed simple-vector out of the NARGS objects   */
1666/*      on top of the vstack; return it in arg_z.  */
1667
1668_spentry(mkstackv)
1669        __(dnode_align(%nargs,tsp_frame.fixed_overhead+node_size,%imm0))
1670        __(TSP_Alloc_Var(%imm0,%arg_y))
1671        __(movl %nargs,%imm0)
1672        __(shll $(num_subtag_bits-fixnumshift),%imm0)
1673        __(movb $subtag_simple_vector,%imm0_b)
1674        __(movl %imm0,(%arg_y))
1675        __(leal fulltag_misc(%arg_y),%arg_z)
1676        __(test %nargs,%nargs)
1677        __(leal misc_data_offset(%arg_z,%nargs),%imm0)
1678        __(jmp 2f)
16791:      __(pop -node_size(%imm0))
1680        __(subl $node_size,%nargs)
1681        __(leal -node_size(%imm0),%imm0)
16822:      __(jne 1b)
1683        __(jmp *%ra0)   
1684_endsubp(mkstackv)
1685
1686        .globl C(egc_write_barrier_start)
1687C(egc_write_barrier_start):
1688/*  */
1689/* The function pc_luser_xp() - which is used to ensure that suspended threads  */
1690/* are suspended in a GC-safe way - has to treat these subprims (which implement  */
1691/* the EGC write-barrier) specially.  Specifically, a store that might introduce  */
1692/* an intergenerational reference (a young pointer stored in an old object) has  */
1693/* to "memoize" that reference by setting a bit in the global "refbits" bitmap.  */
1694/* This has to happen atomically, and has to happen atomically wrt GC.  */
1695
1696/* Note that updating a word in a bitmap is itself not atomic, unless we use  */
1697/* interlocked loads and stores.  */
1698
1699/* For RPLACA and RPLACD, things are fairly simple: regardless of where we are  */
1700/* in the function, we can do the store (even if it's already been done) and  */
1701/* calculate whether or not we need to set the bit out-of-line.  (Actually  */
1702/* setting the bit needs to be done atomically, unless we're sure that other  */
1703/* threads are suspended.)  */
1704/* We can unconditionally set the suspended thread's RIP to the return address.  */
1705
1706_spentry(rplaca)
1707        .globl C(egc_rplaca)
1708C(egc_rplaca):
1709        __(rcmpl(%arg_z,%arg_y))
1710        __(_rplaca(%arg_y,%arg_z))
1711        __(ja 1f)
17120:      __(repret)
17131:      __(movl %arg_y,%imm0)
1714        __(subl lisp_global(ref_base),%imm0)
1715        __(shrl $dnode_shift,%imm0)
1716        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1717        __(jae 0b)
1718        __(ref_global(refbits,%temp0))
1719        __(xorb $31,%imm0_b)
1720        __(lock)
1721        __(btsl %imm0,(%temp0))
1722        __(ret)
1723_endsubp(rplaca)
1724
1725_spentry(rplacd)
1726        .globl C(egc_rplacd)
1727C(egc_rplacd):
1728        __(rcmpl(%arg_z,%arg_y))
1729        __(_rplacd(%arg_y,%arg_z))
1730        __(ja 1f)
17310:      __(repret)
17321:      __(movl %arg_y,%imm0)
1733        __(subl lisp_global(ref_base),%imm0)
1734        __(shrl $dnode_shift,%imm0)
1735        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1736        __(jae 0b)
1737        __(ref_global(refbits,%temp0))
1738        __(xorb $31,%imm0_b)
1739        __(lock)
1740        __(btsl %imm0,(%temp0))
1741        __(ret)
1742_endsubp(rplacd)
1743
1744/* Storing into a gvector can be handled the same way as storing into a CONS. */
1745/* args (src, unscaled-idx, val) in temp0, arg_y, arg_z */
1746_spentry(gvset)
1747        .globl C(egc_gvset)
1748C(egc_gvset):
1749        __(movl %arg_z,misc_data_offset(%temp0,%arg_y))
1750        __(rcmpl(%arg_z,%temp0))
1751        __(ja 1f)
17520:      __(repret)
17531:      __(lea misc_data_offset(%temp0,%arg_y),%imm0)
1754        __(subl lisp_global(ref_base),%imm0)
1755        __(shrl $dnode_shift,%imm0)
1756        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1757        __(jae 0b)
1758        __(ref_global(refbits,%temp1))
1759        __(xorb $31,%imm0_b)
1760        __(lock)
1761        __(btsl %imm0,(%temp1))
1762        __(ret)
1763_endsubp(gvset)
1764
1765/* This is a special case of storing into a gvector: if we need to  */
1766/* memoize the store, record the address of the hash-table vector  */
1767/* in the refmap, as well.  */
1768
1769_spentry(set_hash_key)
1770        .globl C(egc_set_hash_key)
1771C(egc_set_hash_key):
1772        __(movl %arg_z,misc_data_offset(%temp0,%arg_y))
1773        __(rcmpl(%arg_z,%temp0))
1774        __(ja 1f)
17750:      __(repret)
17761:      __(lea misc_data_offset(%temp0,%arg_y),%imm0)
1777        __(subl lisp_global(ref_base),%imm0)
1778        __(shrl $dnode_shift,%imm0)
1779        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1780        __(jae 0b)
1781        __(ref_global(refbits,%temp1))
1782        __(xorb $31,%imm0_b)
1783        __(lock)
1784        __(btsl %imm0,(%temp1))
1785        /* Now memoize the address of the hash vector */
1786        __(movl %temp0,%imm0)
1787        __(subl lisp_global(ref_base),%imm0)
1788        __(shrl $dnode_shift,%imm0)
1789        __(xorb $31,%imm0_b)
1790        __(lock)
1791        __(btsl %imm0,(%temp1))
1792        __(ret)
1793_endsubp(set_hash_key)
1794
1795/* This is a little trickier: if this is interrupted, we need to know  */
1796/* whether or not the STORE-CONDITIONAL (cmpxchgq) has won or not.    */
1797/* If we're interrupted   before the PC has reached the "success_test" label, */
1798/* repeat (luser the PC back to store_node_conditional_retry.)  If
1799        we're at that */
1800/* label with the Z flag set, we won and (may) need to memoize.  */
1801
1802/* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
1803_spentry(store_node_conditional)
1804        .globl C(egc_store_node_conditional)
1805C(egc_store_node_conditional):
1806        __(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
1807        __(sarl $fixnumshift,%temp0)    /* will be fixnum-tagged */
1808        .globl C(egc_store_node_conditional_retry)
1809C(egc_store_node_conditional_retry):     
18100:      __(cmpl %arg_y,misc_data_offset(%temp1,%temp0))
1811        __(movl misc_data_offset(%temp1,%temp0),%imm0)
1812        __(jne 3f)
1813        __(lock)
1814        __(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
1815        .globl C(egc_store_node_conditional_success_test)
1816C(egc_store_node_conditional_success_test):
1817        __(jne 0b)
1818        __(leal misc_data_offset(%temp1,%temp0),%imm0)
1819        __(subl lisp_global(ref_base),%imm0)
1820        __(shrl $dnode_shift,%imm0)
1821        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1822        __(jae 2f)
1823        __(ref_global(refbits,%temp1))
1824        __(xorb $31,%imm0_b)
1825        __(lock)
1826        __(btsl %imm0,(%temp1))
1827        .globl C(egc_store_node_conditional_success_end)
1828C(egc_store_node_conditional_success_end):
18292:      __(movl $t_value,%arg_z)
1830        __(ret)
18313:      __(movl $nil_value,%arg_z)
1832        __(ret)
1833_endsubp(store_node_conditional)
1834
1835        /* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
1836_spentry(set_hash_key_conditional)
1837        .globl C(egc_set_hash_key_conditional)
1838C(egc_set_hash_key_conditional):
1839        __(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
1840        __(sarl $fixnumshift,%temp0)    /* will be fixnum-tagged */
1841        .globl C(egc_set_hash_key_conditional_retry)
1842C(egc_set_hash_key_conditional_retry):         
18430:      __(cmpl %arg_y,misc_data_offset(%temp1,%temp0))
1844        __(movl misc_data_offset(%temp1,%temp0),%imm0)
1845        __(jne 3f)
1846        __(lock)
1847        __(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
1848        .globl C(egc_set_hash_key_conditional_success_test)
1849C(egc_set_hash_key_conditional_success_test):
1850        __(jne 0b)
1851        __(leal misc_data_offset(%temp1,%temp0),%imm0)
1852        __(subl lisp_global(ref_base),%imm0)
1853        __(shrl $dnode_shift,%imm0)
1854        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1855        __(jae 2f)
1856        __(ref_global(refbits,%temp0))
1857        __(xorb $31,%imm0_b)
1858        __(lock)
1859        __(btsl %imm0,(%temp0))
1860        /* Now memoize the address of the hash vector */
1861        __(movl %temp1,%imm0)
1862        __(subl lisp_global(ref_base),%imm0)
1863        __(shrl $dnode_shift,%imm0)
1864        __(xorb $31,%imm0_b)
1865        __(lock)
1866        __(btsl %imm0,(%temp0))
1867        .globl C(egc_write_barrier_end)
1868C(egc_write_barrier_end):
18692:      __(movl $t_value,%arg_z)
1870        __(ret)
18713:      __(movl $nil_value,%arg_z)
1872        __(ret)
1873_endsubp(store_node_conditional)
1874
1875_spentry(setqsym)
1876        __(bt $sym_vbit_const,symbol.flags(%arg_y))
1877        __(jae _SPspecset)
1878        __(mov %arg_y,%arg_z)
1879        __(mov $XCONST,%arg_y)
1880        __(set_nargs(2))
1881        __(jmp _SPksignalerr)
1882_endsubp(setqsym)
1883
1884_spentry(progvsave)
1885        __(push %arg_y)
1886       
1887        /* Error if arg_z isn't a proper list.  That's unlikely,  */
1888        /* but it's better to check now than to crash later.  */
1889       
1890        __(compare_reg_to_nil(%arg_z))
1891        __(movl %arg_z,%temp0)  /* fast   */
1892        __(movl %arg_z,%temp1)  /* slow   */
1893        __(je 9f)               /* Null list is proper   */
18940:
1895        __(extract_lisptag(%temp0,%imm0))
1896        __(cmpb $tag_list,%imm0_b)
1897        __(jne 8f)
1898        __(compare_reg_to_nil(%temp0))
1899        __(je 9f)
1900        __(_cdr(%temp0,%arg_y)) /* (null (cdr fast)) ?   */
1901        __(compare_reg_to_nil(%arg_y))
1902        __(je 9f)
1903        __(extract_lisptag(%arg_y,%imm0))
1904        __(cmpb $tag_list,%imm0_b)
1905        __(jne 8f)
1906        __(_cdr(%arg_y,%temp0))
1907        __(_cdr(%temp1,%temp1))
1908        __(cmpl %temp1,%temp0)
1909        __(jne 0b)
1910
19118:      __(add $node_size,%esp) /* discard pushed arg_y */
1912        __(movl $XIMPROPERLIST,%arg_y)
1913        __(set_nargs(2))
1914        __(jmp _SPksignalerr)
19159:      /* Whew           */
1916
1917        /* Next, determine the length of arg_y.  We   */
1918        /* know that it's a proper list.   */
1919        __(pop %arg_y)
1920       
1921        __(movl $-fixnumone,%imm0)
1922        __(movl %arg_y,%temp0)
19231:      __(compare_reg_to_nil(%temp0))
1924        __(_cdr(%temp0,%temp0))
1925        __(leal fixnumone(%imm0),%imm0)
1926        __(jne 1b)
1927       
1928        /* imm0 is now (boxed) triplet count.  */
1929        /* Determine word count, add 1 (to align), and make room.  */
1930        /*  if count is 0, make an empty tsp frame and exit   */
1931        __(testl %imm0,%imm0)
1932        __(jne 2f)
1933        __(TSP_Alloc_Fixed(2*node_size,%imm0))
1934        __(ret)
19352:      __(movl %imm0,%temp1)
1936        __(add %imm0,%imm0)
1937        __(add %temp1,%imm0)
1938        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
1939        __(TSP_Alloc_Var(%imm0,%temp0))
1940        __(movl %temp1,(%temp0))
1941        __(movd rcontext(tcr.db_link),%mm0)
19423:      __(movl $unbound_marker,%temp0)
1943        __(compare_reg_to_nil(%arg_z))
1944        __(cmovnel cons.car(%arg_z),%temp0)
1945        __(cmovnel cons.cdr(%arg_z),%arg_z)
1946        __(_car(%arg_y,%temp1))
1947        __(_cdr(%arg_y,%arg_y))
1948        __(movl symbol.binding_index(%temp1),%temp1)
1949        __(cmp rcontext(tcr.tlb_limit),%temp1)
1950        __(jb 4f)
1951        __(push %temp1)
1952        __(tlb_too_small())
19534:      __(push %arg_z)
1954        __(movl rcontext(tcr.tlb_pointer),%arg_z)
1955        __(subl $binding.size,%imm0)
1956        __(movl %temp1,binding.sym(%imm0))
1957        __(push (%arg_z,%temp1))
1958        __(pop binding.val(%imm0))
1959        __(movl %temp0,(%arg_z,%temp1))
1960        __(pop %arg_z)
1961        __(movd %mm0,binding.link(%imm0))
1962        __(movd %imm0,%mm0)
1963        __(compare_reg_to_nil(%arg_y))
1964        __(jne 3b)
1965        __(movd %mm0,rcontext(tcr.db_link))
1966        __(ret)
1967_endsubp(progvsave)
1968
1969/* Allocate node objects on the temp stack, immediate objects on the foreign  */
1970/* stack. (The caller has to know which stack to discard a frame from.)  */
1971/* %arg_y = boxed element-count, %arg_z = boxed subtype  */
1972
1973_spentry(stack_misc_alloc)
1974        __(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
1975        __(jne local_label(stack_misc_alloc_not_u24))
1976        __(unbox_fixnum(%arg_z,%imm0))
1977        __(mov %arg_y,%temp0)
1978        __(shl $num_subtag_bits-fixnumshift,%temp0)
1979        __(or %temp0,%imm0)     /* %imm0 now = header */
1980        __(movd %imm0,%mm0)     /* cache header in %mm0 */
1981        __(andb $fulltagmask,%imm0_b)
1982        __(cmpb $fulltag_nodeheader,%imm0_b)
1983        __(je local_label(stack_misc_alloc_node))
1984        __(movd %mm0,%imm0)
1985        __(cmpb $max_32_bit_ivector_subtag,%imm0_b)
1986        __(jbe local_label(stack_misc_alloc_32))
1987        __(cmpb $max_8_bit_ivector_subtag,%imm0_b)
1988        __(jbe local_label(stack_misc_alloc_8))
1989        __(cmpb $max_16_bit_ivector_subtag,%imm0_b)
1990        __(jbe local_label(stack_misc_alloc_16))
1991        __(cmpb $subtag_double_float_vector,%imm0_b)
1992        __(jne local_label(stack_misc_alloc_1))
1993        /* double-float vector case */
1994        __(imul $2,%arg_y,%imm0)
1995        __(jmp local_label(stack_misc_alloc_alloc_ivector))
1996local_label(stack_misc_alloc_1):
1997        __(unbox_fixnum(%arg_y,%imm0))
1998        __(addl $7,%imm0)
1999        __(shrl $3,%imm0)
2000        __(jmp local_label(stack_misc_alloc_alloc_ivector))
2001local_label(stack_misc_alloc_8):
2002        __(unbox_fixnum(%arg_y,%imm0))
2003        __(jmp local_label(stack_misc_alloc_alloc_ivector))
2004local_label(stack_misc_alloc_16):
2005        __(unbox_fixnum(%arg_y,%imm0))
2006        __(shl $1,%imm0)
2007        __(jmp local_label(stack_misc_alloc_alloc_ivector))
2008local_label(stack_misc_alloc_32):
2009        __(mov %arg_y,%imm0)
2010local_label(stack_misc_alloc_alloc_ivector):
2011        /* byte count in %imm0 */
2012        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
2013        __(cmpl $tstack_alloc_limit,%imm0)
2014        __(ja local_label(stack_misc_alloc_heap_alloc_ivector))
2015        __ifdef(`WINDOWS')
2016         __(windows_cstack_probe(%imm0,%temp1))
2017        __endif
2018        __(movd rcontext(tcr.foreign_sp),%stack_temp)
2019        __(movd %stack_temp,%temp1)
2020        __(subl %imm0,rcontext(tcr.foreign_sp))
2021        __(movl rcontext(tcr.foreign_sp),%temp0)
20220:      __(movsd %fpzero,-dnode_size(%temp1))
2023        __(subl $dnode_size,%temp1)
2024        __(cmpl %temp1,%temp0)
2025        __(jnz 0b)
2026        __(movd %stack_temp,(%temp0))
2027        __(movl %ebp,csp_frame.save_ebp(%temp0))
2028        __(movd %mm0,csp_frame.fixed_overhead(%temp0))
2029        __(lea csp_frame.fixed_overhead+fulltag_misc(%temp0),%arg_z)
2030        __(ret)
2031local_label(stack_misc_alloc_heap_alloc_ivector):
2032        __(movd rcontext(tcr.foreign_sp),%stack_temp)
2033        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2034        __(movl rcontext(tcr.foreign_sp),%imm0)
2035        __(movd %stack_temp,(%imm0))
2036        __(jmp _SPmisc_alloc)
2037local_label(stack_misc_alloc_node):
2038        __(movl %arg_y,%imm0)
2039        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
2040        __(cmpl $tstack_alloc_limit,%imm0)
2041        __(ja local_label(stack_misc_alloc_heap_alloc_gvector))
2042        __(TSP_Alloc_Var(%imm0,%temp1))
2043        __(movd %mm0,(%temp1))
2044        __(leal fulltag_misc(%temp1),%arg_z)
2045        __(ret)
2046local_label(stack_misc_alloc_heap_alloc_gvector):
2047        __(TSP_Alloc_Fixed(0,%imm0))
2048        __(jmp _SPmisc_alloc)
2049
2050local_label(stack_misc_alloc_not_u24):
2051        __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_24))
2052_endsubp(stack_misc_alloc)
2053
2054/* subtype (boxed, of course) is pushed, followed by nargs bytes worth of */
2055/* initial-contents.  Note that this can be used to cons any type of */
2056/* initialized node-header'ed misc object (symbols, closures, ...) */
2057/* as well as vector-like objects. */
2058_spentry(gvector)
2059        __(subl $node_size,%nargs)      /* off by one in x862-%gvector */
2060        __(movl (%esp,%nargs),%imm0)    /* boxed subtype */
2061        __(sarl $fixnumshift,%imm0)
2062        __(movl %nargs,%arg_z)
2063        __(shll $num_subtag_bits-word_shift,%arg_z)
2064        __(orl %arg_z,%imm0)
2065        __(movd %imm0,%mm0)
2066        __(dnode_align(%nargs,node_size,%imm0))
2067        __(push %ra0)   /* aka %temp0, can't be live while consing */
2068        __(Misc_Alloc(%arg_z))
2069        __(pop %ra0)
2070        __(movl %nargs,%imm0)
2071        __(jmp 2f)
20721:      __(movl %arg_y,misc_data_offset(%arg_z,%imm0))
20732:      __(subl $node_size,%imm0)
2074        __(pop %arg_y)  /* Note the intentional fencepost: */
2075                        /* discard the subtype as well. */
2076        __(jge 1b)
2077        __(jmp *%ra0)
2078_endsubp(gvector)
2079
2080_spentry(mvpass)
2081        __(hlt)
2082_endsubp(mvpass)
2083
2084_spentry(nthvalue)
2085        __(hlt)
2086_endsubp(nthvalue)
2087
2088_spentry(values)
2089        __(movl (%temp0),%arg_y)        /* return address */
2090        __(ref_global(ret1val_addr,%imm0))
2091        __(movl $nil_value,%arg_z)
2092        __(cmpl %imm0,%arg_y)
2093        __(je 0f)
2094        __(test %nargs,%nargs)
2095        __(cmovne -node_size(%esp,%nargs),%arg_z)
2096        __(movl %temp0,%esp)
2097        __(ret)
20980:      __(movl 4(%temp0),%arg_y)
2099        __(addl $2*node_size,%temp0)
2100        __(lea (%esp,%nargs),%imm0)
2101        __(movd %nargs,%mm0)
2102        __(jmp 2f)
21031:      __(subl $node_size,%imm0)
2104        __(movl (%imm0),%temp1)
2105        __(subl $node_size,%temp0)
2106        __(movl %temp1,(%temp0))
21072:      __(cmp %imm0,%esp)
2108        __(jne 1b)
2109        __(movl %temp0,%esp)
2110        __(movd %mm0,%nargs)
2111        __(jmp *%arg_y)
2112
2113_endsubp(values)
2114
2115_spentry(default_optional_args)
2116        __(hlt)
2117_endsubp(default_optional_args)
2118
2119_spentry(opt_supplied_p)
2120        __(hlt)
2121_endsubp(opt_supplied_p)
2122
2123_spentry(lexpr_entry)
2124        __(hlt)
2125_endsubp(lexpr_entry)
2126
2127_spentry(heap_rest_arg)
2128        __(push_argregs())
2129        __(movl %temp0,%arg_y)
2130        __(movl %nargs,%imm0)
2131        __(testl %imm0,%imm0)
2132        __(movl $nil_value,%arg_z)
2133        __(jmp 2f)
2134        .p2align 4
21351:      __(pop %temp1)
2136        __(Cons(%temp1,%arg_z,%arg_z))
2137        __(subl $node_size,%imm0)
21382:      __(jg 1b)
2139        __(push %arg_z)
2140        __(movl %arg_y,%temp0)
2141        __(jmp *%ra0)
2142
2143_endsubp(heap_rest_arg)
2144
2145/* %imm0 contains the number of fixed args; make an &rest arg out of */
2146/* the others. */
2147_spentry(req_heap_rest_arg)
2148        __(push_argregs())
2149        __(movd %nargs,%mm0)
2150        __(subl %imm0,%nargs)
2151        __(movl %nargs,%imm0)
2152        __(movl %temp0,%temp1)
2153        __(movl $nil_value,%arg_z)
2154        __(jmp 2f)
2155        .p2align 4
21561:      __(pop %arg_y)
2157        __(Cons(%arg_y,%arg_z,%arg_z))
2158        __(subl $node_size,%imm0)
21592:      __(jg 1b)
2160        __(push %arg_z)
2161        __(movl %temp1,%temp0)
2162        __(movd %mm0,%nargs)
2163        __(jmp *%ra0)
2164_endsubp(req_heap_rest_arg)
2165
2166/* %imm0 bytes of stuff has already been pushed   */
2167/* make an &rest arg out of any others   */
2168_spentry(heap_cons_rest_arg)
2169        __(movd %nargs,%mm0)
2170        __(subl %imm0,%nargs)
2171        __(movl %nargs,%imm0)
2172        __(movl $nil_value,%arg_z)
2173        __(movl %ra0,%arg_y)    /* temp0 can't be live while consing */
2174        __(jmp 2f)              /* (did I mention that already?) */
2175        .p2align 4
21761:      __(pop %temp1)
2177        __(Cons(%temp1,%arg_z,%arg_z))
2178        __(subl $node_size,%imm0)
21792:      __(jg 1b)
2180        __(push %arg_z)
2181        __(movd %mm0,%nargs)
2182        __(jmp *%arg_y)
2183_endsubp(heap_cons_rest_arg)
2184
2185_spentry(simple_keywords)
2186        __(xor %imm0,%imm0)
2187        __(push_argregs())
2188        __(jmp _SPkeyword_bind)
2189_endsubp(simple_keywords)
2190
2191_spentry(keyword_args)
2192        __(push_argregs())
2193        __(jmp _SPkeyword_bind)
2194_endsubp(keyword_args)
2195
2196/* There are %nargs words of arguments on the stack; %imm0 contains the */
2197/* number of non-keyword args pushed.  It's possible that we never actually */
2198/* got any keyword args, which would make things much simpler. */
2199
2200/* On entry, the upper half of %temp1 (aka %nargs) contains some bits */
2201/* indicating whether &allow-other-keys and/or &rest was present in the */
2202/* lambda list. */
2203
2204/* Once we get here, we can use the arg registers. */
2205
2206/* N.B.: %ra0 is %temp0, and must not be clobbered. */
2207
2208define(`keyword_flags_aok_bit',`16')
2209define(`keyword_flags_unknown_keys_bit',`17')
2210define(`keyword_flags_rest_bit',`18')
2211define(`keyword_flags_seen_aok_bit',`19')
2212
2213_spentry(keyword_bind)
2214        __(movl %temp1,rcontext(tcr.unboxed0))  /* save keyword flags */
2215        __(movzwl %nargs_w,%nargs)
2216        __(movl %nargs,%arg_z)
2217        __(subl %imm0,%arg_z)
2218        __(jbe local_label(no_keyword_values))
2219        __(btl $word_shift,%arg_z)
2220        __(jnc local_label(even))
2221        __(movl $nil_value,%arg_y)
2222        __(movl %arg_z,%nargs)
2223        __(test %nargs,%nargs)
2224        __(movl %ra0,rcontext(tcr.save0))       /* save temp0 while consing */
2225        __(jmp 1f)
22260:      __(pop %arg_z)
2227        __(Cons(%arg_z,%arg_y,%arg_y))
2228        __(subl $node_size,%nargs)
22291:      __(jnz 0b)
2230        __(movl rcontext(tcr.save0),%ra0)
2231        __(movapd %fpzero,rcontext(tcr.save0))
2232        __(movl %arg_y,%arg_z)
2233        __(movl $XBADKEYS,%arg_y)
2234        __(set_nargs(2))
2235        __(jmp _SPksignalerr)
2236
2237        /* Now that we're sure that we have an even number of */
2238        /* keywords and values (in %arg_z), move the pairs over */
2239        /* to the temp stack. */
2240local_label(even):
2241        __(lea tsp_frame.fixed_overhead(%arg_z),%arg_y)
2242        __(TSP_Alloc_Var(%arg_y,%imm0))
22432:      __(subl $node_size,%arg_y)
2244        __(pop (%arg_y))
2245        __(cmpl %arg_y,%imm0)
2246        __(jne 2b)
2247
2248        /* Get the keyword vector into %arg_y, and its length into %imm0. */
2249        /* Push %imm0 pairs of NILs (representing value, supplied-p) */
2250        /* for each declared keyword. */
2251        __(movzwl misc_data_offset(%fn),%imm0)
2252        /* XXX bootstrapping */
2253        __(btr $15,%imm0)
2254        __(jnc 0f)
2255        __(vector_length(%fn,%arg_y))
2256        __(box_fixnum(%imm0,%imm0))
2257        __(subl %imm0,%arg_y)
2258        __(movl %arg_y,%imm0)
2259        __(shrl $fixnumshift,%imm0)
22600:
2261        __(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
2262        __(vector_length(%arg_y,%imm0))
2263        __(jmp 4f)
22643:      __(push $nil_value)
2265        __(push $nil_value)
22664:      __(subl $fixnumone,%imm0)
2267        __(jge 3b)
2268
2269        /* We can now push %ra0 (aka %temp0) and %nargs (aka %temp1) */
2270        /* in order to get a couple more registers to work with. */
2271        __(push %ra0)
2272        __(push %nargs)
2273
2274        /* At this point we have: */
2275        /* number of supplied keywords and values in %arg_z */
2276        /* keyword vector in %arg_y */
2277        __(vector_length(%arg_y,%imm0))
2278        __(push %imm0)          /* count of declared keywords */
2279        __(push %arg_z)         /* count of supplied keys and values */
2280
2281        /* For each declared keyword, iterate over the supplied k/v pairs */
2282        /* to see if it's supplied and what the value is. */
2283        /* checking to see if any */
2284        /* key-value pairs were unexpectedly supplied. */
2285
2286        __(movl rcontext(tcr.save_tsp),%temp0)
2287        __(addl $2*node_size,%temp0) /* skip frame overhead */
2288        /* %temp0: top of tstack (skipping frame overhead) */
2289        __(lea 4*node_size(%esp,%imm0,2),%temp1)
2290        /* %temp1: word above 0th value/supplied-p pair on vstack */
2291        /* %arg_y: keyword vector */
2292        __(xorl %imm0,%imm0)
2293        /* %imm0: index */
2294        /* %arg_z: temporary */
2295
2296        /* Iterate over supplied k/v pairs on tstack.  See if key is */
2297        /* in the keyword vector.  Copy value and set supplied-p on */
2298        /* vstack if found. */
2299
2300local_label(tstack_loop):
2301        __(movl (%temp0,%imm0,2),%arg_z)        /* keyword */
2302        __(push %imm0)
2303        __(xorl %imm0,%imm0)
2304        __(cmpl $nrs.kallowotherkeys,%arg_z)
2305        __(jne local_label(next_keyvect_entry))
2306        __(btsl $keyword_flags_seen_aok_bit,rcontext(tcr.unboxed0))
2307        __(jc local_label(next_keyvect_entry))
2308        __(push %imm0)
2309        __(movl 4(%esp),%imm0)
2310        __(cmpl $nil_value,node_size(%temp0,%imm0,2))
2311        __(pop %imm0)
2312        __(je local_label(next_keyvect_entry))
2313        __(btsl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2314        __(jmp local_label(next_keyvect_entry))
2315        /* loop through keyword vector */
23166:      __(cmpl misc_data_offset(%arg_y,%imm0),%arg_z)
2317        __(jne 7f)
2318        /* Got a match; have we already seen this keyword? */
2319        __(negl %imm0)
2320        __(cmpl $nil_value,-node_size*2(%temp1,%imm0,2))
2321        __(jne 9f)      /* seen it, ignore this value */
2322        __(movl (%esp),%arg_z)
2323        __(lea (%temp0,%arg_z,2),%arg_z)
2324        __(movl node_size(%arg_z),%arg_z) /* value for this key */
2325        __(movl %arg_z,-node_size(%temp1,%imm0,2))
2326        __(movl $t_value,-node_size*2(%temp1,%imm0,2))
2327        __(jmp 9f)
23287:      __(addl $node_size,%imm0)
2329local_label(next_keyvect_entry):
2330        __(cmpl %imm0,8(%esp))
2331        __(jne 6b)
2332        /* Didn't match anything in the keyword vector.  Is the keyword */
2333        /* :allow-other-keys? */
2334        __(cmpl $nrs.kallowotherkeys,%arg_z)
2335        __(je 9f)       /* :allow-other-keys is never "unknown" */
23368:      __(btsl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
23379:      __(pop %imm0)
2338        __(addl $fixnumone,%imm0)
2339        __(movl %imm0,%arg_z)
2340        __(shll $1,%arg_z)      /* pairs of tstack words */
2341        __(cmpl %arg_z,0(%esp))
2342        __(jne local_label(tstack_loop))
2343
2344        __(pop %imm0)   /* count of supplied keys and values */
2345        __(addl $node_size,%esp)
2346        __(pop %nargs)
2347        __(pop %ra0)
2348
2349        /* If the function takes an &rest arg, or if we got an unrecognized */
2350        /* keyword and don't allow that, copy the incoming k/v pairs from */
2351        /* the temp stack back to the value stack. */
2352        __(btl $keyword_flags_rest_bit,rcontext(tcr.unboxed0))
2353        __(jc 1f)
2354        __(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
2355        __(jnc 0f)
2356        __(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2357        __(jnc 1f)
2358        /* pop the tstack frame */
23590:      __(discard_temp_frame(%imm0))
2360        __(jmp *%ra0)
2361
2362        /* Copy the k/v pairs from the tstack back to the value stack, */
2363        /* either because the function takes an &rest arg or because */
2364        /* we need to signal an "unknown keywords" error. */
23651:      __(movl rcontext(tcr.save_tsp),%arg_z)
2366        __(mov (%arg_z),%arg_y)
2367        __(jmp 3f)
23682:      __(push (%arg_z))
2369        __(push node_size(%arg_z))
23703:      __(addl $dnode_size,%arg_z)
2371        __(cmpl %arg_z,%arg_y)
2372        __(jne 2b)
2373        __(discard_temp_frame(%arg_z))
2374        __(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
2375        __(jnc 9f)
2376        __(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2377        __(jc 9f)
2378        /* Signal an "unknown keywords" error */
2379        __(movl %imm0,%nargs)
2380        __(movl $nil_value,%arg_z)
2381        __(test %nargs,%nargs)
2382        __(movl %ra0,rcontext(tcr.save0))
2383        __(jmp 5f)
23844:      __(pop %arg_y)
2385        __(Cons(%arg_y,%arg_z,%arg_z))
2386        __(subl $node_size,%nargs)
23875:      __(jnz 4b)
2388        __(movl $XBADKEYS,%arg_y)
2389        __(set_nargs(2))
2390        __(movl rcontext(tcr.save0),%ra0)
2391        __(movl $0,rcontext(tcr.save0))
2392        __(jmp _SPksignalerr)
23939:      __(jmp *%ra0)
2394
2395/* No keyword value were provided.  Access the keyword vector (which is the */
2396/* 0th constant in %fn), determine its length N, and push N pairs of NILs. */
2397/* N could be 0... */
2398
2399local_label(no_keyword_values):
2400        __(movzwl misc_data_offset(%fn),%imm0)
2401        /* XXX bootstrapping */
2402        __(btr $15,%imm0)
2403        __(jnc 9f)
2404        __(vector_length(%fn,%arg_y))
2405        __(box_fixnum(%imm0,%imm0))
2406        __(subl %imm0,%arg_y)
2407        __(movl %arg_y,%imm0)
2408        __(shrl $fixnumshift,%imm0)
24099:
2410        __(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
2411        __(vector_length(%arg_y,%arg_z))
2412        __(movl $nil_value,%imm0)
2413        __(jmp 1f)
24140:      __(push %imm0)
2415        __(push %imm0)
24161:      __(subl $fixnumone,%arg_z)
2417        __(jge 0b)
2418        __(jmp *%ra0)
2419_endsubp(keyword_bind)
2420
2421/* Normally, we'd just set %fname (aka %temp0) and do */
2422/* jump_fname().  Sometimes, though, %temp0 is being used */
2423/* as %ra0, and I'm not sure that it's going to be safe to */
2424/* clobber that.  (Note that nil-relative symbols aren't going */
2425/* get moved around by the GC, so we can get away with putting */
2426/* '%err-disp in %imm0.) */
2427_spentry(ksignalerr)
2428        __(mov $nrs.errdisp,%imm0)
2429        __(mov symbol.fcell(%imm0),%fn)
2430        __(jump_fn)
2431_endsubp(ksignalerr)
2432
2433_spentry(stack_rest_arg)
2434        __(xorl %imm0,%imm0)
2435        __(push_argregs())
2436        __(jmp _SPstack_cons_rest_arg)
2437_endsubp(stack_rest_arg)
2438
2439_spentry(req_stack_rest_arg)
2440        __(push_argregs())
2441        __(jmp _SPstack_cons_rest_arg)
2442_endsubp(req_stack_rest_arg)
2443
2444_spentry(stack_cons_rest_arg)
2445        __(movd %nargs,%mm2)
2446        __(movl %temp0,rcontext(tcr.save0))
2447        __(subl %imm0,%temp1)
2448        __(movl $nil_value,%arg_z)
2449        __(jle 2f)      /* empty list; make an empty TSP frame */
2450        __(addl %temp1,%temp1)
2451        __(cmpl $(tstack_alloc_limit-dnode_size),%temp1)
2452        __(ja 3f)       /* make empty frame, then heap-cons */
2453        __(dnode_align(%temp1,tsp_frame.fixed_overhead,%imm0))
2454        __(TSP_Alloc_Var(%imm0,%temp0))
2455        __(addl $fulltag_cons,%temp0)
24561:      __(pop %arg_y)
2457        __(_rplacd(%temp0,%arg_z))
2458        __(_rplaca(%temp0,%arg_y))
2459        __(movl %temp0,%arg_z)
2460        __(addl $cons.size,%temp0)
2461        __(subl $dnode_size,%temp1)
2462        __(jne 1b)
2463        __(push %arg_z)
2464        __(movd %mm2,%nargs)
2465        __(movl rcontext(tcr.save0),%temp0)
2466        __(movss %fpzero,rcontext(tcr.save0))
2467        __(jmp *%temp0)
2468/* Length 0, make empty frame */
24692:
2470        __(TSP_Alloc_Fixed(0,%temp0))
2471        __(push %arg_z)
2472        __(movd %mm2,%nargs)
2473        __(movl rcontext(tcr.save0),%temp0)
2474        __(movss %fpzero,rcontext(tcr.save0))
2475        __(jmp *%temp0)
2476/* Too big to stack-cons, but make an empty frame before heap-consing */
2477        __(TSP_Alloc_Fixed(0,%temp0))
2478        __(movd %mm2,%nargs)
2479        __(movl rcontext(tcr.save0),%temp0)
2480        __(movss %fpzero,rcontext(tcr.save0))
2481        __(jmp _SPheap_cons_rest_arg)
2482_endsubp(stack_cons_rest_arg)
2483
2484_spentry(getxlong)
2485        __(hlt)
2486_endsubp(getxlong)
2487
2488/* Have to be a little careful here: the caller may or may not have pushed  */
2489/* an empty frame, and we may or may not have needed one.  We can't easily  */
2490/* tell whether or not a frame will be needed (if the caller didn't reserve  */
2491/* a frame, whether or not we need one depends on the length of the list  */
2492/* in arg_z.  So, if the caller didn't push a frame, we do so; once */
2493/* everything's been spread, we discard the reserved frame (regardless of
2494/* who pushed it) if all args fit in registers.   */
2495
2496/* xxx preserve temp1 somehow? cf. comment in x862-invoke-fn */
2497_spentry(spreadargz)
2498        __(test %nargs,%nargs)
2499        __(jne 0f)
2500        __(push $reserved_frame_marker)
2501        __(push $reserved_frame_marker)
25020:      __(movl %arg_z,rcontext(tcr.save0))     /* save in case of error */
2503        __(movd %nargs,%mm0)    /* now we can use %temp1 */
2504        __(xorl %nargs,%nargs)
2505        __(cmpl $nil_value,%arg_z)
2506        __(je 2f)
25071:      __(extract_fulltag(%arg_z,%imm0))
2508        __(cmpb $fulltag_cons,%imm0_b)
2509        __(jne 9f)
2510        __(_car(%arg_z,%arg_y))
2511        __(_cdr(%arg_z,%arg_z))
2512        __(add $node_size,%nargs)
2513        __(cmpl $call_arguments_limit<<fixnumshift,%nargs)
2514        __(jae 8f)
2515        __(push %arg_y)
2516        __(cmpl $nil_value,%arg_z)
2517        __(jne 1b)
25182:      __(movd %mm0,%imm0)
2519        __(addl %imm0,%nargs)
2520        __(jne 4f)
25213:      __(addl $2*node_size,%esp)
2522        __(movl $0,rcontext(tcr.save0))
2523        __(jmp *%ra0)
25244:      __(pop %arg_z)
2525        __(cmp $1*node_size,%nargs)
2526        __(je 3b)
2527        __(pop %arg_y)
2528        __(cmp $2*node_size,%nargs)
2529        __(je 3b)
2530        __(movl $0,rcontext(tcr.save0))
2531        __(jmp *%ra0)
2532/* Discard everything that's been pushed already, complain */
25338:      __(lea (%esp,%nargs),%esp)
2534        __(movl rcontext(tcr.save0),%arg_z) /* recover original */
2535        __(movl $0,rcontext(tcr.save0))
2536        __(movl $XTMINPS,%arg_y)
2537        __(set_nargs(2))
2538        __(push %ra0)
2539        __(jmp _SPksignalerr)
25409:      __(lea (%esp,%nargs),%esp)
2541        __(movl rcontext(tcr.save0),%arg_z) /* recover original */
2542        __(movl $0,rcontext(tcr.save0))
2543        __(movl $XNOSPREAD,%arg_y)
2544        __(set_nargs(2))
2545        __(push %ra0)
2546        __(jmp _SPksignalerr)
2547_endsubp(spreadargz)
2548
2549
2550/* Caller built its own frame when it was entered.  If all outgoing args  */
2551/* are in registers, we can discard that frame; otherwise, we copy outgoing  */
2552/* relative to it and restore %rbp/%ra0   */
2553_spentry(tfuncallgen)
2554        __(cmpl $nargregs*node_size,%nargs)
2555        __(jbe 9f)
2556        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2557        __(movl %temp0,rcontext(tcr.save0))
2558        __(movd %nargs,%mm0)
2559        __(xorl %temp1,%temp1)
2560        /* We can use %ra0 as a temporary here, since the real return address */
2561        /* is on the stack   */
25620:      __(movl -node_size(%imm0),%ra0)
2563        __(movl %ra0,-node_size(%ebp,%temp1))
2564        __(subl $node_size,%imm0)
2565        __(subl $node_size,%temp1)
2566        __(cmpl %imm0,%esp)
2567        __(jne 0b)
2568        __(lea (%ebp,%temp1),%esp)
2569        __(movl 4(%ebp),%ra0)
2570        __(movl (%ebp),%ebp)
2571        __(pushl %ra0)
2572        __(movd %mm0,%nargs)
2573        __(movl rcontext(tcr.save0),%temp0)
2574        __(movss %fpzero,rcontext(tcr.save0))
2575        __(do_funcall())
2576        /* All args in regs; exactly the same as the tfuncallvsp case   */
25779:             
2578        __(leave)
2579        __(do_funcall())
2580
2581_endsubp(tfuncallgen)
2582
2583/* Some args were pushed; move them down in the frame   */
2584_spentry(tfuncallslide)
2585        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2586        __(movd %nargs,%mm0)
2587        __(xorl %temp1,%temp1)
2588        __(movl %temp0,rcontext(tcr.save0))
25890:      __(movl -node_size(%imm0),%temp0)
2590        __(movl %temp0,-node_size(%ebp,%temp1))
2591        __(subl $node_size,%imm0)
2592        __(subl $node_size,%temp1)
2593        __(cmpl %imm0,%esp)
2594        __(jne 0b)
2595        __(lea (%ebp,%temp1),%esp)
2596        __(push 4(%ebp))        /* return address */
2597        __(movl (%ebp),%ebp)
2598        __(movd %mm0,%nargs)
2599        __(movl rcontext(tcr.save0),%temp0)
2600        __(movss %fpzero,rcontext(tcr.save0))
2601        __(do_funcall())
2602_endsubp(tfuncallslide)
2603
2604/* No args were pushed; recover saved context & do funcall        */
2605_spentry(tfuncallvsp)
2606        __(leave)
2607        __(do_funcall())
2608_endsubp(tfuncallvsp)
2609
2610_spentry(tcallsymgen)
2611        __(cmpl $nargregs*node_size,%nargs)
2612        __(jbe 9f)
2613        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2614        __(movd %nargs,%mm0)
2615        __(movl %temp0,rcontext(tcr.save0))
2616        __(xorl %temp1,%temp1)  /* aka nargs */
26170:      __(movl -node_size(%imm0),%temp0)
2618        __(movl %temp0,-node_size(%ebp,%temp1))
2619        __(subl $node_size,%imm0)
2620        __(subl $node_size,%temp1)
2621        __(cmpl %imm0,%esp)
2622        __(jne 0b)
2623        __(lea (%ebp,%temp1),%esp)
2624        __(movl 4(%ebp),%temp0)
2625        __(movl (%ebp),%ebp)
2626        __(push %temp0)
2627        __(movl rcontext(tcr.save0),%temp0)
2628        __(movss %fpzero,rcontext(tcr.save0))
2629        __(movd %mm0,%nargs)
2630        __(jump_fname())
2631/* All args in regs; exactly the same as the tcallsymvsp case. */
26329:
2633        __(leave)
2634        __(jump_fname())
2635_endsubp(tcallsymgen)
2636
2637_spentry(tcallsymslide)
2638        __(movl %ebp,%imm0)
2639        __(subl %nargs,%imm0)
2640        __(addl $nargregs*node_size,%imm0)      /* new tos */
2641        __(push %imm0)
2642        __(push %arg_y)
2643        __(push %arg_z)
2644        __(push %nargs)
2645        __(lea (4-nargregs)*node_size(%esp,%nargs),%arg_y) /* src ptr */
2646        __(movl %ebp,%imm0) /* dst ptr */
2647        __(subl $fixnumone*nargregs,%nargs)
2648        __(jmp 1f)
26490:      __(subl $node_size,%arg_y)
2650        __(movl (%arg_y),%arg_z)
2651        __(subl $node_size,%imm0)
2652        __(movl %arg_z,(%imm0))
26531:      __(subl $fixnumone,%nargs)
2654        __(jge 0b)
2655        __(pop %nargs)
2656        __(pop %arg_z)
2657        __(pop %arg_y)
2658        __(pop %esp)
2659        __(push node_size(%ebp))
2660        __(movl 0(%ebp),%ebp)
2661        __(jump_fname)
2662_endsubp(tcallsymslide)
2663
2664_spentry(tcallsymvsp)
2665        __(leave)
2666        __(jump_fname())
2667_endsubp(tcallsymvsp)
2668
2669_spentry(tcallnfngen)
2670        __(cmpl $nargregs*node_size,%nargs)
2671        __(jbe 9f)
2672        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2673        __(movd %nargs,%mm0)    /* stash nargs aka temp1 */
2674        __(xorl %temp1,%temp1)
2675        __(movl %temp0,rcontext(tcr.save0))
2676        /* It's OK to use %ra0 (%temp0) as an temp here, since the */
2677        /* real return address is on the stack. */
26780:      __(movl -node_size(%imm0),%ra0)
2679        __(movl %ra0,-node_size(%ebp,%temp1))
2680        __(subl $node_size,%imm0)
2681        __(subl $node_size,%temp1)
2682        __(cmpl %imm0,%esp)
2683        __(jne 0b)
2684        __(movl rcontext(tcr.save0),%fn)
2685        __(movss %fpzero,rcontext(tcr.save0))
2686        __(lea (%ebp,%temp1),%esp)
2687        __(movl lisp_frame.savera0(%ebp),%ra0)
2688        __(movl lisp_frame.backlink(%ebp),%ebp)
2689        __(push %ra0)
2690        __(movd %mm0,%nargs)
2691        __(jmp *%fn)
26929:      /* All args in regs; exactly the same as the tcallnfnvsp case */
2693        __(movl %temp0,%fn)
2694        __(leave)
2695        __(jmp *%fn)
2696_endsubp(tcallnfngen)
2697
2698_spentry(tcallnfnslide)
2699        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2700        __(movd %nargs,%mm0)    /* save nargs aka temp1 */
2701        __(xorl %temp1,%temp1)
2702        __(movl %temp0,rcontext(tcr.save0))
2703        /* We can use %ra0 as a temporary here, since the real return address */
2704        /* is on the stack   */
27050:      __(movl -node_size(%imm0),%ra0)
2706        __(movl %ra0,-node_size(%ebp,%temp1))
2707        __(subl $node_size,%imm0)
2708        __(subl $node_size,%temp1)
2709        __(cmpl %imm0,%esp)
2710        __(jne 0b)
2711        __(movl rcontext(tcr.save0),%fn)
2712        __(lea (%ebp,%temp1),%esp)
2713        __(movl lisp_frame.savera0(%ebp),%ra0)
2714        __(movl lisp_frame.backlink(%ebp),%ebp)
2715        __(push %ra0)
2716        __(movapd %fpzero,rcontext(tcr.save0))
2717        __(movd %mm0,%nargs)
2718        __(jmp *%fn)
2719_endsubp(tcallnfnslide)
2720
2721_spentry(tcallnfnvsp)
2722        __(mov %temp0,%fn)
2723        __(leave)
2724        __(jmp *%fn)
2725_endsubp(tcallnfnvsp)
2726
2727/* Make a "raw" area on the foreign stack, stack-cons a macptr to point */
2728/* to it, and return the macptr.  Size (in bytes, boxed) is in arg_z */
2729/* on entry; macptr in arg_z on exit. */
2730_spentry(makestackblock)
2731        __(check_cstack_alignment())
2732        __(unbox_fixnum(%arg_z,%imm0))
2733        __(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
2734        __(cmpl $tstack_alloc_limit,%imm0)
2735        __(jae 1f)
2736        __ifdef(`WINDOWS')
2737         __(windows_cstack_probe(%imm0,%arg_z))
2738        __endif
2739        __(movd rcontext(tcr.foreign_sp),%mm0)
2740        __(subl %imm0,rcontext(tcr.foreign_sp))
2741        __(movl rcontext(tcr.foreign_sp),%arg_z)
2742        __(movd %mm0,(%arg_z))
2743        __(movl %ebp,csp_frame.save_ebp(%arg_z))
2744        __(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
2745        __(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
2746        __(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
2747        __(movl %imm0,macptr.address(%arg_z))
2748        __(movss %fpzero,macptr.domain(%arg_z))
2749        __(movss %fpzero,macptr.type(%arg_z))
2750        __(ret)
27511:      __(movd rcontext(tcr.foreign_sp),%mm0)
2752        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2753        __(movl rcontext(tcr.foreign_sp),%imm0)
2754        __(movd %mm0,(%imm0))
2755        __(movl %ebp,csp_frame.save_ebp(%imm0))
2756        __(set_nargs(1))
2757        __(movl $nrs.new_gcable_ptr,%fname)
2758        __(jump_fname())
2759_endsubp(makestackblock)
2760
2761_spentry(makestackblock0)
2762        __(unbox_fixnum(%arg_z,%imm0))
2763        __(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
2764        __(cmpl $tstack_alloc_limit,%imm0)
2765        __(jae 9f)
2766        __ifdef(`WINDOWS')
2767         __(windows_cstack_probe(%imm0,%temp0))
2768        __endif
2769        __(movl rcontext(tcr.foreign_sp),%temp0)
2770        __(subl %imm0,rcontext(tcr.foreign_sp))
2771        __(movl rcontext(tcr.foreign_sp),%arg_z)
2772        __(movl %temp0,(%arg_z))
2773        __(movl %ebp,csp_frame.save_ebp(%arg_z))
2774        __(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
2775        __(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
2776        __(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
2777        __(movl %imm0,macptr.address(%arg_z))
2778        __(movss %fpzero,macptr.domain(%arg_z))
2779        __(movss %fpzero,macptr.type(%arg_z))
2780        __(jmp 2f)
27811:      __(movsd %fpzero,(%imm0))
2782        __(addl $dnode_size,%imm0)
27832:      __(cmpl %imm0,%temp0)
2784        __(jne 1b)
2785        __(repret)
27869:      __(movd rcontext(tcr.foreign_sp),%mm0)
2787        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2788        __(movl rcontext(tcr.foreign_sp),%imm0)
2789        __(movd %mm0,(%imm0))
2790        __(movl %ebp,csp_frame.save_ebp(%imm0))
2791        __(set_nargs(1))
2792        __(movl $nrs.new_gcable_ptr,%fname)
2793        __(jump_fname())
2794_endsubp(makestackblock0)
2795
2796_spentry(makestacklist)
2797        __(test %arg_y,%arg_y)
2798        __(js 9f)
2799        __(movl %arg_y,%imm0)
2800        __(testb $fixnummask,%imm0_b)
2801        __(jne 9f)
2802        __(addl %imm0,%imm0)
2803        __(rcmpl(%imm0,$tstack_alloc_limit))
2804        __(movl $nil_value,%temp1)
2805        __(jae 2f)
2806        __(addl $tsp_frame.fixed_overhead,%imm0)
2807        __(TSP_Alloc_Var(%imm0,%temp0))
2808        __(addl $fulltag_cons,%temp0)
2809        __(jmp 1f)
28100:      __(_rplaca(%temp0,%arg_z))
2811        __(_rplacd(%temp0,%temp1))
2812        __(movl %temp0,%temp1)
2813        __(addl $cons.size,%temp0)
28141:      __(subl $fixnumone,%arg_y)
2815        __(jge 0b)
2816        __(movl %temp1,%arg_z)
2817        __(ret)
28182:      __(TSP_Alloc_Fixed(0,%imm0))
2819        __(jmp 4f)
28203:      __(Cons(%arg_z,%temp1,%temp1))
28214:      __(subl $fixnumone,%arg_y)                             
2822        __(jge 3b)
2823        __(movl %temp1,%arg_z)
2824        __(ret)
28259:      __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte))
2826_endsubp(makestacklist)
2827
2828/* subtype (boxed) vpushed before initial values. (Had better be a */
2829/* node header subtag.)  Nargs set to count of things vpushed. */
2830_spentry(stkgvector)
2831        __(movl -fixnumone(%esp,%nargs),%imm0)  /* boxed subtag */
2832        __(shrl $fixnumshift,%imm0)
2833        __(leal -fixnumone(%nargs),%arg_z)
2834        __(movl %arg_z,%arg_y)
2835        __(shll $num_subtag_bits-fixnumshift,%arg_z)
2836        __(orl %arg_z,%imm0)    /* imm0 = header, %arg_y = unaligned size */
2837        __(movd %imm0,%mm0)
2838        __(dnode_align(%arg_y,(tsp_frame.fixed_overhead+node_size),%imm0))
2839        __(TSP_Alloc_Var(%imm0,%arg_z))
2840        __(movd %mm0,(%arg_z))
2841        __(addl $fulltag_misc,%arg_z)
2842        __(lea -node_size(%nargs),%imm0)
2843        __(jmp 2f)
28441:      __(pop misc_data_offset(%arg_z,%imm0))
28452:      __(subl $node_size,%imm0)
2846        __(jge 1b)
2847        __(addl $node_size,%esp)
2848        __(jmp *%ra0)
2849_endsubp(stkgvector)
2850
2851/* Allocate a fulltag-misc object. */
2852/* arg_y = boxed element count, arg_z = subtag (boxed, of course) */
2853_spentry(misc_alloc)
2854        __(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
2855        __(jne local_label(misc_alloc_not_u24))
2856        __(unbox_fixnum(%arg_z,%imm0))
2857        __(mov %arg_y,%temp0)
2858        __(shl $num_subtag_bits-fixnumshift,%temp0)
2859        __(or %temp0,%imm0)     /* %imm0 now = header */
2860        __(movd %imm0,%mm0)     /* Misc_Alloc wants header in %mm0 */
2861        __(andb $fulltagmask,%imm0_b)
2862        __(cmpb $fulltag_nodeheader,%imm0_b)
2863        __(je local_label(misc_alloc_32))
2864        __(movd %mm0,%imm0)
2865        __(cmpb $max_32_bit_ivector_subtag,%imm0_b)
2866        __(jbe local_label(misc_alloc_32))
2867        __(cmpb $max_8_bit_ivector_subtag,%imm0_b)
2868        __(jbe local_label(misc_alloc_8))
2869        __(cmpb $max_16_bit_ivector_subtag,%imm0_b)
2870        __(jbe local_label(misc_alloc_16))
2871        __(cmpb $subtag_double_float_vector,%imm0_b)
2872        __(jne local_label(misc_alloc_1))
2873        /* double-float vector case */
2874        __(imul $2,%arg_y,%imm0)
2875        __(jmp local_label(misc_alloc_alloc_vector))
2876local_label(misc_alloc_1):
2877        __(unbox_fixnum(%arg_y,%imm0))
2878        __(addl $7,%imm0)
2879        __(shrl $3,%imm0)
2880        __(jmp local_label(misc_alloc_alloc_vector))
2881local_label(misc_alloc_8):
2882        __(unbox_fixnum(%arg_y,%imm0))
2883        __(jmp local_label(misc_alloc_alloc_vector))
2884local_label(misc_alloc_16):
2885        __(unbox_fixnum(%arg_y,%imm0))
2886        __(shl $1,%imm0)
2887        __(jmp local_label(misc_alloc_alloc_vector))
2888local_label(misc_alloc_32):
2889        __(movl %arg_y,%imm0)
2890local_label(misc_alloc_alloc_vector):
2891        __(dnode_align(%imm0,node_size,%imm0))
2892        __(Misc_Alloc(%arg_z))
2893        __(ret)
2894local_label(misc_alloc_not_u24):
2895        __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_24))
2896_endsubp(misc_alloc)
2897
2898/* N.B. arg count word in %imm0, not %nargs */
2899/* no %whole_reg;  it's in rcontext(tcr.save0) */
2900/* %arg_reg is %temp1, key vector in %arg_y */
2901_startfn(C(destbind1))
2902        __(movl %ra0,rcontext(tcr.save1))
2903        /* Save entry %esp in case of error   */
2904        __(movd %esp,%mm0)
2905        /* Save arg count word */
2906        __(movd %imm0,%mm1)
2907        /* Extract required arg count.   */
2908        __(testb %imm0_b,%imm0_b)
2909        __(je local_label(opt))         /* skip if no required args   */
2910        __(movzbl %imm0_b,%imm0)
2911local_label(req_loop): 
2912        __(compare_reg_to_nil(%arg_reg))
2913        __(je local_label(toofew))
2914        __(movb $fulltagmask,%imm0_bh)
2915        __(andb %arg_reg_b,%imm0_bh)
2916        __(cmpb $fulltag_cons,%imm0_bh)
2917        __(jne local_label(badlist))
2918        __(subb $1,%imm0_b)
2919        __(pushl cons.car(%arg_reg))
2920        __(_cdr(%arg_reg,%arg_reg))
2921        __(jne local_label(req_loop))
2922        __(movd %mm1,%imm0)
2923local_label(opt):
2924        __(movb %imm0_bh,%imm0_b)
2925        __(testb %imm0_b,%imm0_b)
2926        __(je local_label(rest_keys))
2927        __(btl $initopt_bit,%imm0)
2928        __(jc local_label(opt_supp))
2929        /* 'simple' &optionals:  no supplied-p, default to nil.   */
2930local_label(simple_opt_loop):
2931        __(compare_reg_to_nil(%arg_reg))
2932        __(je local_label(default_simple_opt))
2933        __(movb $fulltagmask,%imm0_bh)
2934        __(andb %arg_reg_b,%imm0_bh)
2935        __(cmpb $fulltag_cons,%imm0_bh)
2936        __(jne local_label(badlist))
2937        __(subb $1,%imm0_b)
2938        __(pushl cons.car(%arg_reg))
2939        __(_cdr(%arg_reg,%arg_reg))
2940        __(jne local_label(simple_opt_loop))
2941        __(jmp local_label(rest_keys))
2942local_label(default_simple_opt):
2943        __(subb $1,%imm0_b)
2944        __(pushl $nil_value)
2945        __(jne local_label(default_simple_opt))
2946        __(jmp local_label(rest_keys))
2947local_label(opt_supp):
2948        __(movb $fulltagmask,%imm0_bh)
2949        __(andb %arg_reg_b,%imm0_bh)
2950        __(compare_reg_to_nil(%arg_reg))
2951        __(je local_label(default_hard_opt))
2952        __(cmpb $fulltag_cons,%imm0_bh)
2953        __(jne local_label(badlist))
2954        __(subb $1,%imm0_b)
2955        __(pushl cons.car(%arg_reg))
2956        __(_cdr(%arg_reg,%arg_reg))
2957        __(push $t_value)
2958        __(jne local_label(opt_supp))
2959        __(jmp local_label(rest_keys))
2960local_label(default_hard_opt):
2961        __(subb $1,%imm0_b)
2962        __(push $nil_value)
2963        __(push $nil_value)
2964        __(jne local_label(default_hard_opt))
2965local_label(rest_keys):
2966        __(btl $restp_bit,%imm0)
2967        __(jc local_label(have_rest))
2968        __(btl $keyp_bit,%imm0)
2969        __(jc local_label(have_keys))
2970        __(compare_reg_to_nil(%arg_reg))
2971        __(jne local_label(toomany))
2972        __(movss %fpzero,rcontext(tcr.save0))
2973        __(jmp *%ra0)
2974local_label(have_rest):
2975        __(pushl %arg_reg)
2976        __(btl $keyp_bit,%imm0)
2977        __(jc local_label(have_keys))
2978        __(movss %fpzero,rcontext(tcr.save0))
2979        __(jmp *%ra0)
2980        /* Ensure that arg_reg contains a proper,even-length list.  */
2981        /* Insist that its length is <= 512 (as a cheap circularity check.)   */
2982local_label(have_keys):
2983        __(movb $255,%imm0_b)
2984        __(push %arg_reg)
2985        __(push %arg_z)
2986        __(xorl %arg_z,%arg_z)
2987local_label(count_keys_loop):
2988        __(compare_reg_to_nil(%arg_reg))
2989        __(je local_label(counted_keys))
2990        __(subb $1,%imm0_b)
2991        __(jb local_label(toomany))
2992        __(movb $fulltagmask,%arg_z_bh)
2993        __(andb %arg_reg_b,%arg_z_bh)
2994        __(cmpb $fulltag_cons,%arg_z_bh)
2995        __(jne local_label(badlist))
2996        __(_cdr(%arg_reg,%arg_reg))
2997        __(compare_reg_to_nil(%arg_reg))
2998        __(je local_label(badlist))
2999        __(movb $fulltagmask,%arg_z_bh)
3000        __(andb %arg_reg_b,%arg_z_bh)
3001        __(cmpb $fulltag_cons,%arg_z_bh)
3002        __(jne local_label(badlist))
3003        __(_cdr(%arg_reg,%arg_reg))
3004        __(jmp local_label(count_keys_loop))
3005local_label(counted_keys):             
3006        /* We've got a proper, even-length list of key/value pairs in  */
3007        /* arg_reg. For each keyword var in the lambda-list, push a pair  */
3008        /* of NILs on the vstack.   */
3009        __(pop %arg_z)
3010        __(pop %arg_reg)
3011        __(movd %mm1,%imm0)
3012        __(shrl $16,%imm0)
3013        __(movzbl %imm0_b,%imm0)
3014        __(movl %esp,rcontext(tcr.unboxed0))    /* 0th value/supplied-p pair */
3015        __(jmp local_label(push_pair_test))
3016local_label(push_pair_loop):
3017        __(push $nil_value)
3018        __(push $nil_value)
3019local_label(push_pair_test):   
3020        __(subb $1,%imm0_b)
3021        __(jge local_label(push_pair_loop))
3022        __(push %temp0) /* keyword */
3023        __(push %arg_z) /* value */
3024        __(vector_length(%arg_y,%imm0))
3025        __(push %arg_reg)
3026        __(push %imm0)  /* keyword vector length */
3027        __(movd %mm1,%imm0)
3028        __(movl $0,rcontext(tcr.unboxed1)) /* count of unknown keywords seen */
3029local_label(match_keys_loop):
3030        __(movl 4(%esp),%arg_reg)
3031        __(compare_reg_to_nil(%arg_reg))
3032        __(je local_label(matched_keys))
3033        __(_car(%arg_reg,%temp0))
3034        __(_cdr(%arg_reg,%arg_reg))
3035        __(_car(%arg_reg,%arg_z))
3036        __(_cdr(%arg_reg,%arg_reg))
3037        __(movl %arg_reg,4(%esp))
3038        __(xorl %temp1,%temp1)
3039        __(jmp local_label(match_test))
3040local_label(match_loop):
3041        __(cmpl misc_data_offset(%arg_y,%temp1),%temp0)
3042        __(je local_label(matched))
3043        __(addl $node_size,%temp1)
3044local_label(match_test):
3045        __(cmpl %temp1,(%esp))  /* compare index, keyword vector length */
3046        __(jne local_label(match_loop))
3047        /* No match.  Note unknown keyword, check for :allow-other-keys   */
3048        __(addl $1,rcontext(tcr.unboxed1))
3049        __(cmpl $nrs.kallowotherkeys,%temp0)
3050        __(jne local_label(match_keys_loop))
3051        __(subl $1,rcontext(tcr.unboxed1))
3052        __(btsl $seen_aok_bit,%imm0)
3053        __(jc local_label(match_keys_loop))
3054        /* First time we've seen :allow-other-keys.  Maybe set aok_bit.   */
3055        __(compare_reg_to_nil(%arg_z))
3056        __(je local_label(match_keys_loop))
3057        __(btsl $aok_bit,%imm0)
3058        __(jmp local_label(match_keys_loop))
3059        /* Got a match.  Worry about :allow-other-keys here, too.   */
3060local_label(matched):
3061        __(negl %temp1)
3062        __(shll $1,%temp1)
3063        __(addl rcontext(tcr.unboxed0),%temp1)
3064        __(cmpl $nil_value,-node_size*2(%temp1))
3065        __(jne local_label(match_keys_loop))
3066        __(movl %arg_z,-node_size(%temp1))
3067        __(movl $t_value,-node_size*2(%temp1))
3068        __(cmpl $nrs.kallowotherkeys,%temp0)
3069        __(jne local_label(match_keys_loop))
3070        __(btsl $seen_aok_bit,%imm0)
3071        __(jnc local_label(match_keys_loop))
3072        __(compare_reg_to_nil(%arg_z))
3073        __(je local_label(match_keys_loop))
3074        __(btsl $aok_bit,%imm0)
3075        __(jmp local_label(match_keys_loop))
3076local_label(matched_keys):     
3077        __(cmpl $0,rcontext(tcr.unboxed1))      /* any unknown keys seen? */
3078        __(je local_label(keys_ok))
3079        __(btl $aok_bit,%imm0)
3080        __(jnc local_label(badkeys))
3081local_label(keys_ok):
3082        __(addl $(3*node_size),%esp)
3083        __(pop %ra0)
3084        __(movss %fpzero,rcontext(tcr.save0))
3085        __(jmp *%ra0)
3086        /* Some unrecognized keywords.  Complain generically about   */
3087        /* invalid keywords.   */
3088local_label(badkeys):
3089        __(movl $XBADKEYS,%arg_y)
3090        __(jmp local_label(destructure_error))
3091local_label(toomany):
3092        __(movl $XCALLTOOMANY,%arg_y)
3093        __(jmp local_label(destructure_error))
3094local_label(toofew):
3095        __(movl $XCALLTOOFEW,%arg_y)
3096        __(jmp local_label(destructure_error))
3097local_label(badlist):
3098        __(movl $XCALLNOMATCH,%arg_y)
3099local_label(destructure_error):
3100        __(movd %mm0,%esp)              /* undo everything done to the stack */
3101        __(movl rcontext(tcr.save0),%arg_z)     /* %whole_reg */
3102        __(movss %fpzero,rcontext(tcr.save0))
3103        __(set_nargs(2))
3104        __(push %ra0)
3105        __(jmp _SPksignalerr)
3106_endfn(C(destbind1))
3107
3108_spentry(macro_bind)
3109        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3110        __(extract_fulltag(%arg_reg,%imm0))
3111        __(cmpb $fulltag_cons,%imm0_b)
3112        __(jne 1f)
3113        __(_cdr(%arg_reg,%arg_reg))
3114        __(jmp C(destbind1))
31151:      __(movl $XCALLNOMATCH,%arg_y)
3116        __(movl rcontext(tcr.save0),%arg_z)
3117        __(movss %fpzero,rcontext(tcr.save0))
3118        __(set_nargs(2))
3119        __(push %ra0)       
3120        __(jmp _SPksignalerr)
3121
3122_endsubp(macro_bind)
3123
3124_spentry(destructuring_bind)
3125        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3126        __(jmp C(destbind1))
3127_endsubp(destructuring_bind)
3128
3129_spentry(destructuring_bind_inner)
3130        __(movl %arg_z,rcontext(tcr.save0))     /* %whole_reg */
3131        __(jmp C(destbind1))
3132_endsubp(destructuring_bind_inner)
3133
3134_spentry(vpopargregs)
3135        __(hlt)
3136_endsubp(vpopargregs)
3137
3138/* If arg_z is an integer, return in imm0 something whose sign  */
3139/* is the same as arg_z's.  If not an integer, error.   */
3140_spentry(integer_sign)
3141        __(mov %arg_z,%imm0)
3142        __(testb $tagmask,%arg_z_b)
3143        __(je 8f)
3144        __(extract_typecode(%arg_z,%imm0))
3145        __(cmpb $subtag_bignum,%imm0_b)
3146        __(jne 9f)
3147        __(getvheader(%arg_z,%imm0))
3148        __(shr $num_subtag_bits,%imm0)
3149        __(movl misc_data_offset-4(%arg_z,%imm0,4),%imm0)
31508:      __(repret)
31519:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_integer))
3152_endsubp(integer_sign)
3153
3154/* "slide" nargs worth of values up the stack.  imm0 contains */
3155/* the difference between the current stack pointer and the target. */
3156_spentry(mvslide)
3157        __(movd %nargs,%mm0)
3158        __(lea (%esp,%nargs),%arg_y)
3159        __(lea (%arg_y,%imm0),%imm0)
3160        __(test %nargs,%nargs)
3161        __(je 2f)
31621:
3163        __(subl $node_size,%arg_y)
3164        __(movl (%arg_y),%arg_z)
3165        __(subl $node_size,%imm0)
3166        __(movl %arg_z,(%imm0))
3167        __(subl $node_size,%nargs)
3168        __(jne 1b)
31692:      __(movl %imm0,%esp)
3170        __(movd %mm0,%nargs)
3171        __(jmp *%ra0)
3172_endsubp(mvslide)
3173
3174_spentry(save_values)
3175        __(movd rcontext(tcr.save_tsp),%mm1)
3176/* common exit: nargs = values in this set, mm1 = ptr to tsp before call to save_values   */
3177local_label(save_values_to_tsp):
3178        __(movl %ra0,rcontext(tcr.save0))
3179        __(movl rcontext(tcr.save_tsp),%temp0)
3180        __(dnode_align(%nargs,tsp_frame.fixed_overhead+(2*node_size),%imm0)) /* count, link   */
3181        __(TSP_Alloc_Var(%imm0,%arg_z))
3182        __(movl rcontext(tcr.save_tsp),%imm0)
3183        __(movd %mm1,(%imm0))
3184        __(movl %nargs,(%arg_z))
3185        __(movl %temp0,node_size(%arg_z))
3186        __(leal 2*node_size(%arg_z,%nargs),%arg_y)
3187        __(leal (%esp,%nargs),%imm0)
3188        __(cmpl %imm0,%esp)
3189        __(jmp 2f)
31901:      __(subl $node_size,%imm0)
3191        __(movl (%imm0),%arg_z)
3192        __(subl $node_size,%arg_y)
3193        __(cmpl %imm0,%esp)
3194        __(movl %arg_z,(%arg_y))
31952:      __(jne 1b)
3196        __(addl %nargs,%esp)
3197        __(movl rcontext(tcr.save0),%ra0)
3198        __(movl $0,rcontext(tcr.save0))
3199        __(jmp *%ra0)
3200_endsubp(save_values)
3201
3202/* Add the multiple values that are on top of the vstack to the set  */
3203/* saved in the top tsp frame, popping them off of the vstack in the  */
3204/* process.  It is an error (a bad one) if the TSP contains something  */
3205/* other than a previously saved set of multiple-values.  */
3206/* Since adding to the TSP may cause a new TSP segment to be allocated,  */
3207/* each add_values call adds another linked element to the list of  */
3208/* values. This makes recover_values harder.   */
3209_spentry(add_values)
3210        /* do we need to preserve imm0? */
3211        __(test %nargs,%nargs)
3212        __(movl rcontext(tcr.save_tsp),%imm0)
3213        __(movl (%imm0),%imm0)
3214        __(movd %imm0,%mm1)     /* for the benefit of save_values_to_tsp */
3215        __(jne local_label(save_values_to_tsp))
3216        __(jmp *%ra0)
3217_endsubp(add_values)
3218
3219/* push the values in the value set atop the sp, incrementing nargs.  */
3220/* Discard the tsp frame; leave values atop the sp.   */
3221_spentry(recover_values)
3222        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3223        __(movd %nargs,%mm0)              /* temp1 */
3224        /* First, walk the segments reversing the pointer to previous  */
3225        /* segment pointers Can tell the end because that previous  */
3226        /* segment pointer is the prev tsp pointer   */
3227        __(movl rcontext(tcr.save_tsp),%temp1)
3228        __(movl %temp1,%temp0)  /* current segment   */
3229        __(movl %temp1,%arg_y)  /* last segment   */
3230        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3231local_label(walkloop):
3232        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3233        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3234        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3235        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3236        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3237        __(jne local_label(walkloop))
3238
3239        __(movl %temp1,%arg_z)
3240        __(movd %mm0,%nargs)
3241        /* the final segment pointer is now in %arg_y  */
3242        /* walk backwards, pushing values on the stack and incrementing %nargs   */
3243local_label(pushloop):
3244        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment   */
3245        __(test %imm0,%imm0)
3246        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3247        __(leal (%nargs,%imm0),%nargs)
3248        __(jmp 2f)
32491:      __(push -node_size(%temp0))
3250        __(subl $node_size,%temp0)
3251        __(subl $fixnum_one,%imm0)
32522:      __(jne 1b)
3253        __(cmpl %arg_y,%arg_z)
3254        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3255        __(jne local_label(pushloop))
3256        __(movl (%arg_z),%arg_z)
3257        __(movl %arg_z,rcontext(tcr.save_tsp))
3258        __(movl %arg_z,rcontext(tcr.next_tsp))
3259        __(movl rcontext(tcr.save0),%ra0)
3260        __(movl $0,rcontext(tcr.save0))
3261        __(jmp *%ra0)           
3262_endsubp(recover_values)
3263
3264/* Exactly like recover_values, but it's necessary to reserve an outgoing  */
3265/* frame if any values (which will be used as outgoing arguments) will  */
3266/* wind up on the stack.  We can assume that %nargs contains 0 (and  */
3267/* that no other arguments have been pushed) on entry.   */
3268
3269_spentry(recover_values_for_mvcall)
3270        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3271        /* First, walk the segments reversing the pointer to previous  */
3272        /* segment pointers Can tell the end because that previous  */
3273        /* segment pointer is the prev tsp pointer   */
3274        __(xorl %nargs,%nargs)
3275        __(push %nargs)
3276        __(movl rcontext(tcr.save_tsp),%temp1)
3277        __(movl %temp1,%temp0)  /* current segment   */
3278        __(movl %temp1,%arg_y)  /* last segment   */
3279        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3280local_label(walkloop_mvcall):
3281        __(movl tsp_frame.data_offset(%temp0),%imm0)
3282        __(addl %imm0,(%esp))
3283        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3284        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3285        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3286        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3287        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3288        __(jne local_label(walkloop_mvcall))
3289
3290        __(movl %temp1,%arg_z)
3291        __(pop %nargs)
3292
3293        __(cmpl $nargregs*node_size,%nargs)
3294        __(jbe local_label(pushloop_mvcall))
3295        __(push $reserved_frame_marker)
3296        __(push $reserved_frame_marker)
3297
3298        /* the final segment pointer is now in %arg_y  */
3299        /* walk backwards, pushing values on the stack and incrementing %nargs*/
3300local_label(pushloop_mvcall):
3301        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment */
3302        __(test %imm0,%imm0)
3303        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3304        __(jmp 2f)
33051:      __(push -node_size(%temp0))
3306        __(subl $node_size,%temp0)
3307        __(subl $fixnum_one,%imm0)
33082:      __(jne 1b)
3309        __(cmpl %arg_y,%arg_z)
3310        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3311        __(jne local_label(pushloop_mvcall))
3312        __(movl (%arg_z),%arg_z)
3313        __(movl %arg_z,rcontext(tcr.save_tsp))
3314        __(movl %arg_z,rcontext(tcr.next_tsp))
3315        __(movl rcontext(tcr.save0),%ra0)
3316        __(movl $0,rcontext(tcr.save0))
3317        __(jmp *%ra0)           
3318_endsubp(recover_values_for_mvcall)
3319
3320_spentry(reset)
3321        __(hlt)
3322_endsubp(reset)
3323
3324/* temp0 = element-count, arg_y = subtag, arg_z = initval */
3325_spentry(misc_alloc_init)
3326        __(push %ebp)
3327        __(movl %esp,%ebp)
3328        __(push %arg_z)
3329        __(movl %arg_y,%arg_z)
3330        __(movl %temp0,%arg_y)
3331        __(push $local_label(misc_alloc_init_back))
3332        __(jmp _SPmisc_alloc)
3333__(tra(local_label(misc_alloc_init_back)))
3334        __(pop %arg_y)
3335        __(leave)
3336        __(movl $nrs.init_misc,%fname)
3337        __(set_nargs(2))
3338        __(jump_fname())
3339_endsubp(misc_alloc_init)
3340
3341/* %temp1 = element-count, %arg_y = subtag, %arg_z = initial-value */       
3342_spentry(stack_misc_alloc_init)
3343        __(push %ebp)
3344        __(movl %esp,%ebp)
3345        __(push %arg_z)
3346        __(movl %arg_y,%arg_z)
3347        __(movl %temp1,%arg_y)
3348        __(pushl $local_label(stack_misc_alloc_init_back))
3349        __(jmp _SPstack_misc_alloc)
3350__(tra(local_label(stack_misc_alloc_init_back)))
3351        __(popl %arg_y)
3352        __(leave)
3353        __(movl $nrs.init_misc,%fname)
3354        __(set_nargs(2))
3355        __(jump_fname())
3356_endsubp(stack_misc_alloc_init)
3357
3358        .globl C(popj)
3359_spentry(popj)
3360C(popj):
3361        __(leave)
3362        __(ret)
3363_endsubp(popj)
3364
3365/* arg_z should be of type (signed-byte 64) */
3366/* return unboxed value in mm0 */
3367_spentry(gets64)
3368        __(testb $fixnummask,%arg_z_b)
3369        __(jne 1f)
3370        __(unbox_fixnum(%arg_z,%imm0))
3371        __(movd %imm0,%mm0)
3372        __(jns 8f)
3373        /* get sign into upper half of %mm0 */
3374        __(pcmpeqd %mm1,%mm1)   /* all ones */
3375        __(psllq $32,%mm1)
3376        __(por %mm1,%mm0)
3377        __(ret)
33781:      __(movb %arg_z_b,%imm0_b)
3379        __(andb $tagmask,%imm0_b)
3380        __(cmpb $tag_misc,%imm0_b)
3381        __(jne 9f)
3382        __(movl misc_header_offset(%arg_z),%imm0)
3383        __(cmpb $subtag_bignum,%imm0_b)
3384        __(jne 9f)
3385        __(cmpl $two_digit_bignum_header,%imm0)
3386        __(ja 9f)
3387        __(movd misc_data_offset(%arg_z),%mm0)
3388        __(jne 8f)
3389        __(movq misc_data_offset(%arg_z),%mm0)
33908:      __(repret)
33919:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_s64))
3392_endsubp(gets64)
3393
3394/* arg_z should be of type (unsigned-byte 64) */
3395/* return unboxed value in mm0 */
3396_spentry(getu64)
3397        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3398        __(testl %arg_z,%imm0)
3399        __(movl %arg_z,%imm0)
3400        __(jne 1f)
3401        __(sarl $fixnumshift,%imm0)
3402        __(movd %imm0,%mm0)
3403        __(ret)
34041:      __(andb $tagmask,%imm0_b)
3405        __(cmpb $tag_misc,%imm0_b)
3406        __(jne 9f)
3407        __(movl misc_header_offset(%arg_z),%imm0)
3408        __(cmpb $subtag_bignum,%imm0_b)
3409        __(jne 9f)
3410        __(cmpl $three_digit_bignum_header,%imm0)
3411        __(ja 9f)
3412        __(je 3f)
3413        __(cmpl $two_digit_bignum_header,%imm0)
3414        __(je 2f)
3415        /* must be a one digit bignum */
3416        __(movl misc_data_offset(%arg_z),%imm0)
3417        __(test %imm0,%imm0)
3418        __(js 9f)
3419        __(movd %imm0,%mm0)
3420        __(ret)
34212:      __(movl misc_data_offset+4(%arg_z),%imm0)
3422        __(testl %imm0,%imm0)
3423        __(js 9f)
3424        __(movq misc_data_offset(%arg_z),%mm0)
3425        __(ret)
34263:      __(movl misc_data_offset(%arg_z),%imm0)
3427        __(cmpl $0,misc_data_offset+8(%arg_z))
3428        __(jne 9f)
3429        __(movq misc_data_offset(%arg_z),%mm0)
3430        __(repret)
34319:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_u64))
3432_endsubp(getu64)
3433
3434/* Make unsigned integer from value in mm0 */
3435_spentry(makeu64)
3436        __(movq %mm0,%mm1)
3437        __(psrlq $32,%mm0)
3438        __(movd %mm0,%imm0)
3439        __(test %imm0,%imm0)
3440        __(js 3f)
3441        __(jnz 2f)
3442        __(movd %mm1,%imm0)
3443        __(cmpl $target_most_positive_fixnum,%imm0)
3444        __(ja 1f)
3445        __(box_fixnum(%imm0,%arg_z))
3446        __(ret)
34471:      /* maybe make a 1 digit bignum */
3448        __(test %imm0,%imm0)
3449        __(js 2f)
3450        __(movl $one_digit_bignum_header,%imm0)
3451        __(movd %imm0,%mm0)
3452        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3453        __(movd %mm1,misc_data_offset(%arg_z))
3454        __(ret)
3455        /* make a 2 digit bignum */
34562:      __(movl $two_digit_bignum_header,%imm0)
3457        __(movd %imm0,%mm0)
3458        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3459        __(movq %mm1,misc_data_offset(%arg_z))
3460        __(ret)
3461        /* make a 3 digit bignum */
34623:      __(movl $three_digit_bignum_header,%imm0)
3463        __(movd %imm0,%mm0)
3464        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(3)))
3465        __(movq %mm1,misc_data_offset(%arg_z))
3466        __(ret)
3467_endsubp(makeu64)
3468
3469/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
3470/* unbound_marker), arg_y = symbol */
3471_spentry(specref)
3472        __(movl symbol.binding_index(%arg_z),%imm0)
3473        __(cmp rcontext(tcr.tlb_limit),%imm0)
3474        __(movl rcontext(tcr.tlb_pointer),%temp1)
3475        __(movl %arg_z,%arg_y)
3476        __(jae 1f)
3477        __(movl (%temp1,%imm0),%arg_z)
3478        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3479        __(cmovel symbol.vcell(%arg_y),%arg_z)
3480        __(ret)
34811:      __(movl symbol.vcell(%arg_y),%arg_z)
3482        __(ret)
3483_endsubp(specref)
3484
3485/* arg_y = special symbol, arg_z = new value. */
3486_spentry(specset)
3487        __(movl symbol.binding_index(%arg_y),%imm0)
3488        __(cmp rcontext(tcr.tlb_limit),%imm0)
3489        __(movl rcontext(tcr.tlb_pointer),%temp1)
3490        __(jae 1f)
3491        __(movl (%temp1,%imm0),%temp0)
3492        __(cmpb $no_thread_local_binding_marker,%temp0_b)
3493        __(je 1f)
3494        __(movl %arg_z,(%temp1,%imm0))
3495        __(ret)
34961:      __(movl %arg_y,%temp0)
3497        __(movl $1<<fixnumshift,%arg_y)
3498        __(jmp _SPgvset)
3499_endsubp(specset)
3500
3501_spentry(specrefcheck)
3502        __(mov %arg_z,%arg_y)
3503        __(movl symbol.binding_index(%arg_z),%imm0)
3504        __(cmp rcontext(tcr.tlb_limit),%imm0)
3505        __(jae 7f)
3506        __(movl rcontext(tcr.tlb_pointer),%temp1)
3507        __(movl (%temp1,%imm0),%arg_z)
3508        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3509        __(cmovel symbol.vcell(%arg_y),%arg_z)
3510        __(cmpb $unbound_marker,%arg_z_b)
3511        __(je 9f)
35128:      __(repret)
35137:      __(movl symbol.vcell(%arg_y),%arg_z)
3514        __(cmpb $unbound_marker,symbol.vcell(%arg_y))
3515        __(je 9f)
3516        __(repret)
35179:      __(uuo_error_reg_unbound(Rarg_y))
3518_endsubp(specrefcheck)
3519
3520_spentry(restoreintlevel)
3521        __(hlt)
3522_endsubp(restoreintlevel)
3523
3524/* Make a lisp integer from the unsigned value in imm0 */
3525_spentry(makeu32)
3526        __(cmpl $target_most_positive_fixnum,%imm0)
3527        __(ja 0f)       /* need to make a bignum */
3528        __(box_fixnum(%imm0,%arg_z))
3529        __(ret)
35300:      __(movd %imm0,%mm1)
3531        __(test %imm0,%imm0)
3532        __(js 1f)
3533        __(movl $one_digit_bignum_header,%imm0)
3534        __(movd %imm0,%mm0)
3535        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3536        __(movd %mm1,misc_data_offset(%arg_z))
3537        __(ret)
35381:      __(movl $two_digit_bignum_header,%imm0)
3539        __(movd %imm0,%mm0)
3540        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3541        __(movd %mm1,misc_data_offset(%arg_z))
3542        __(ret)
3543_endsubp(makeu32)
3544
3545/* arg_z is of type (signed-byte 32) */
3546/* return unboxed value in %imm0 */
3547_spentry(gets32)
3548        __(testb $fixnummask,%arg_z_b)
3549        __(jne 1f)
3550        __(unbox_fixnum(%arg_z,%imm0))
3551        __(ret)
35521:      __(movb %arg_z_b,%imm0_b)
3553        __(andb $tagmask,%imm0_b)
3554        __(cmpb $tag_misc,%imm0_b)
3555        __(jne 9f)
3556        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3557        __(cmpb $subtag_bignum,%imm0_b)
3558        __(jne 9f)
3559        __(movl misc_header_offset(%arg_z),%imm0)
3560        __(cmpl $one_digit_bignum_header,%imm0)
3561        __(jne 9f)
3562        __(movl misc_data_offset(%arg_z),%imm0)
3563        __(ret)
35649:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_signed_byte_32))
3565_endsubp(gets32)
3566
3567/* arg_z is of type (unsigned-byte 32) */
3568/* return unboxed value in %imm0 */
3569_spentry(getu32)
3570        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3571        __(testl %arg_z,%imm0)
3572        __(movl %arg_z,%imm0)
3573        __(jne 1f)
3574        __(sarl $fixnumshift,%imm0)
3575        __(ret)
35761:      __(andb $tagmask,%imm0_b)
3577        __(cmpb $tag_misc,%imm0_b)
3578        __(jne 9f)
3579        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3580        __(cmpb $subtag_bignum,%imm0_b)
3581        __(jne 9f)
3582        __(movl misc_header_offset(%arg_z),%imm0)
3583        __(cmpl $two_digit_bignum_header,%imm0)
3584        __(je 2f)
3585        __(cmpl $one_digit_bignum_header,%imm0)
3586        __(jne 9f)
3587        __(movl misc_data_offset(%arg_z),%imm0)
3588        __(ret)
35892:      __(movl misc_data_offset(%arg_z),%imm0)
3590        __(cmpl $0,misc_data_offset+4(%arg_z))
3591        __(jne 9f)
3592        __(ret)
35939:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_unsigned_byte_32))
3594_endsubp(getu32)
3595
3596_spentry(mvpasssym)
3597        __(hlt)
3598_endsubp(mvpasssym)
3599
3600/* don't smash arg_z */
3601_spentry(unbind)
3602        __(push %arg_z)
3603        __(movl rcontext(tcr.db_link),%imm0)
3604        __(movl rcontext(tcr.tlb_pointer),%arg_z)
3605        __(movl binding.sym(%imm0),%temp0)
3606        __(movl binding.val(%imm0),%arg_y)
3607        __(movl binding.link(%imm0),%imm0)
3608        __(movl %arg_y,(%arg_z,%temp0))
3609        __(movl %imm0,rcontext(tcr.db_link))
3610        __(pop %arg_z)
3611        __(ret)
3612_endsubp(unbind)
3613
3614_spentry(unbind_n)
3615        __(push %temp1)         /* preserve temp1/nargs */
3616        __(push %arg_z)
3617        __(xorl %arg_z,%arg_z)
3618        __(movl rcontext(tcr.db_link),%temp1)
3619        __(movl rcontext(tcr.tlb_pointer),%arg_z)
36201:             
3621        __(movl binding.sym(%temp1),%temp0)
3622        __(movl binding.val(%temp1),%arg_y)
3623        __(movl binding.link(%temp1),%temp1)
3624        __(movl %arg_y,(%arg_z,%temp0))
3625        __(decl %imm0)
3626        __(jne 1b)
3627        __(movl %temp1,rcontext(tcr.db_link))
3628        __(pop %arg_z)
3629        __(pop %temp1)
3630        __(ret)
3631_endsubp(unbind_n)
3632
3633_spentry(unbind_to)
3634        __(push %arg_y)
3635        __(push %arg_z)
3636        __(push %temp0)
3637        __(push %temp1)
3638       
3639        __(movl rcontext(tcr.db_link),%temp0)
3640        __(movl rcontext(tcr.tlb_pointer),%arg_z)
36411:
3642        __(movl binding.sym(%temp0),%temp1)
3643        __(movl binding.val(%temp0),%arg_y)
3644        __(movl binding.link(%temp0),%temp0)
3645        __(movl %arg_y,(%arg_z,%temp1))
3646        __(cmpl %temp0,%imm0)
3647        __(jne 1b)
3648        __(movl %temp0,rcontext(tcr.db_link))
3649
3650        __(pop %temp1)
3651        __(pop %temp0)
3652        __(pop %arg_z)
3653        __(pop %arg_y)
3654        __(ret)
3655_endsubp(unbind_to)
3656
3657_spentry(bind_interrupt_level_0)
3658        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3659        __(cmpl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3660        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3661        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3662        __(push rcontext(tcr.db_link))
3663        __(movl %esp,rcontext(tcr.db_link))
3664        __(movl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3665        __(js 1f)
36660:      __(jmp *%ra0)
3667        /* Interrupt level was negative; interrupt may be pending */
36681:      __(check_pending_enabled_interrupt(2f))
36692:      __(jmp *%ra0)
3670_endsubp(bind_interrupt_level_0)
3671
3672/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect  */
3673/* of disabling interrupts.)   */
3674_spentry(bind_interrupt_level_m1)
3675        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3676        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3677        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3678        __(push rcontext(tcr.db_link))
3679        __(movl %esp,rcontext(tcr.db_link))
3680        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3681        __(jmp *%ra0)
3682_endsubp(bind_interrupt_level_m1)
3683
3684/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
3685/* do what _SPbind_interrupt_level_0 does. */
3686_spentry(bind_interrupt_level)
3687        __(test %arg_z,%arg_z)
3688        __(jz _SPbind_interrupt_level_0)
3689        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3690        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3691        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3692        __(push rcontext(tcr.db_link))
3693        __(movl %esp,rcontext(tcr.db_link))
3694        __(movl %arg_z,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3695        __(jmp *%ra0)
3696_endsubp(bind_interrupt_level)
3697
3698/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
3699/* non-negative, check for pending interrupts. */
3700_spentry(unbind_interrupt_level)
3701        __(btl $TCR_FLAG_BIT_PENDING_SUSPEND,rcontext(tcr.flags))
3702        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3703        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_y),%imm0)
3704        __(jc 5f)
37050:      __(test %imm0,%imm0)
3706        __(movl rcontext(tcr.db_link),%imm0)
3707        __(movl binding.val(%imm0),%temp0)
3708        __(movl binding.link(%imm0),%imm0)
3709        __(movl %temp0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3710        __(movl %imm0,rcontext(tcr.db_link))
3711        __(js 3f)
37122:      __(repret)
37133:      __(test %temp0,%temp0)
3714        __(js 2b)
3715        __(check_pending_enabled_interrupt(4f))
37164:      __(repret)
37175:       /* Missed a suspend request; force suspend now if we're restoring
3718          interrupt level to -1 or greater */
3719        __(cmpl $-2<<fixnumshift,%imm0)
3720        __(jne 0b)
3721        __(movl rcontext(tcr.db_link),%temp0)
3722        __(movl binding.val(%temp0),%temp0)
3723        __(cmpl %imm0,%temp0)
3724        __(je 0b)
3725        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3726        __(suspend_now())
3727        __(jmp 0b)
3728_endsubp(unbind_interrupt_level)
3729
3730_spentry(progvrestore)
3731        __(movl rcontext(tcr.save_tsp),%imm0)
3732        __(movl tsp_frame.backlink(%imm0),%imm0) /* ignore .SPnthrowXXX values frame   */
3733        __(movl tsp_frame.data_offset(%imm0),%imm0)
3734        __(shrl $fixnumshift,%imm0)
3735        __(jne _SPunbind_n)
3736        __(repret)
3737_endsubp(progvrestore)
3738
3739/* %arg_z <- %arg_y + %arg_z.  Do the fixnum case - including overflow -  */
3740/* inline.  Call out otherwise.   */
3741_spentry(builtin_plus)
3742        __(movl %arg_y,%imm0)
3743        __(orl %arg_z,%imm0)
3744        __(testb $fixnummask,%imm0_b)
3745        __(jne 1f)
3746        __(addl %arg_y,%arg_z)
3747        __(jo C(fix_one_bit_overflow))
3748        __(repret)
37491:      __(jump_builtin(_builtin_plus,2))
3750_endsubp(builtin_plus)
3751
3752/* %arg_z <- %arg_y - %arg_z.  Do the fixnum case - including overflow -  */
3753/*  inline.  Call out otherwise.   */
3754_spentry(builtin_minus)
3755        __(movl %arg_y,%imm0)
3756        __(orl %arg_z,%imm0)
3757        __(testb $fixnummask,%imm0_b)
3758        __(jne 1f)
3759        __(xchgl %arg_y,%arg_z)
3760        __(subl %arg_y,%arg_z)
3761        __(jo C(fix_one_bit_overflow))
3762        __(repret)
37631:      __(jump_builtin(_builtin_minus,2))
3764_endsubp(builtin_minus)
3765
3766/* %arg_z -< arg_y * arg_z. */
3767/* Do the fixnum case---including overflow---inline.  Call out otherwise. */
3768_spentry(builtin_times)
3769        __(movl %arg_y,%imm0)
3770        __(orb %arg_z_b,%imm0_b)
3771        __(testb $fixnummask,%imm0_b)
3772        __(jne 2f)
3773        __(unbox_fixnum(%arg_z,%imm0))
3774        /* 32-bit fixnum result in %imm0.  Overflow set if it doesn't fit. */
3775        __(imul %arg_y,%imm0)
3776        __(jo 1f)
3777        __(movl %imm0,%arg_z)
3778        __(ret)
37791:      __(unbox_fixnum(%arg_z,%eax))
3780        __(mark_as_imm(%edx))
3781        __(unbox_fixnum(%arg_y,%edx))
3782        __(imul %edx)
3783        __(movd %eax,%mm0)
3784        __(movd %edx,%mm1)
3785        __(mark_as_node(%edx))
3786        __(psllq $32,%mm1)
3787        __(por %mm1,%mm0)
3788        __(jmp _SPmakes64)
37892:      __(jump_builtin(_builtin_times,2))
3790_endsubp(builtin_times)
3791
3792_spentry(builtin_div)
3793        __(jump_builtin(_builtin_div,2))
3794
3795/* %arg_z <- (= %arg_y %arg_z).   */
3796_spentry(builtin_eq)
3797        __(movl %arg_y,%imm0)
3798        __(orb %arg_z_b,%imm0_b)
3799        __(testb $fixnummask,%imm0_b)
3800        __(jne 1f)
3801        __(rcmpl(%arg_z,%arg_y))
3802        __(condition_to_boolean(e,%imm0,%arg_z))
3803        __(ret)
38041:      __(jump_builtin(_builtin_eq,2))
3805_endsubp(builtin_eq)
3806
3807/* %arg_z <- (/= %arg_y %arg_z).          */
3808_spentry(builtin_ne)
3809        __(movl %arg_y,%imm0)
3810        __(orb %arg_z_b,%imm0_b)
3811        __(testb $fixnummask,%imm0_b)
3812        __(jne 1f)
3813        __(rcmpl(%arg_z,%arg_y))
3814        __(condition_to_boolean(ne,%imm0,%arg_z))
3815        __(ret)
38161:      __(jump_builtin(_builtin_ne,2))
3817_endsubp(builtin_ne)
3818
3819/* %arg_z <- (> %arg_y %arg_z).   */
3820_spentry(builtin_gt)
3821        __(movl %arg_y,%imm0)
3822        __(orb %arg_z_b,%imm0_b)
3823        __(testb $fixnummask,%imm0_b)
3824        __(jne 1f)
3825        __(rcmpl(%arg_y,%arg_z))
3826        __(condition_to_boolean(g,%imm0,%arg_z))
3827        __(ret)
38281:      __(jump_builtin(_builtin_gt,2))
3829_endsubp(builtin_gt)
3830
3831/* %arg_z <- (>= %arg_y %arg_z).          */
3832_spentry(builtin_ge)
3833        __(movl %arg_y,%imm0)
3834        __(orb %arg_z_b,%imm0_b)
3835        __(testb $fixnummask,%imm0_b)
3836        __(jne 1f)
3837        __(rcmpl(%arg_y,%arg_z))
3838        __(condition_to_boolean(ge,%imm0,%arg_z))
3839        __(ret)
38401:      __(jump_builtin(_builtin_ge,2))
3841_endsubp(builtin_ge)
3842
3843/* %arg_z <- (< %arg_y %arg_z).   */
3844_spentry(builtin_lt)
3845        __(movl %arg_y,%imm0)
3846        __(orb %arg_z_b,%imm0_b)
3847        __(testb $fixnummask,%imm0_b)
3848        __(jne 1f)
3849        __(rcmpl(%arg_y,%arg_z))
3850        __(condition_to_boolean(l,%imm0,%arg_z))
3851        __(ret)
38521:      __(jump_builtin(_builtin_lt,2))
3853_endsubp(builtin_lt)
3854
3855/* %arg_z <- (<= %arg_y %arg_z).   */
3856_spentry(builtin_le)
3857        __(movl %arg_y,%imm0)
3858        __(orb %arg_z_b,%imm0_b)
3859        __(testb $fixnummask,%imm0_b)
3860        __(jne 1f)
3861        __(rcmpl(%arg_y,%arg_z))
3862        __(condition_to_boolean(le,%imm0,%arg_z))
3863        __(ret)
38641:      __(jump_builtin(_builtin_le,2))
3865_endsubp(builtin_le)
3866
3867_spentry(builtin_eql)
3868        __(cmpl %arg_y,%arg_z)
3869        __(je 1f)
3870        /* Not EQ.  Could only possibly be EQL if both are tag-misc  */
3871        /* and both have the same subtag. */
3872        __(movl %arg_y,%imm0)
3873        __(andb $tagmask,%imm0_b)
3874        __(cmpb $tag_misc,%imm0_b)
3875        __(jne 2f)
3876        __(movb %arg_z_b,%imm0_bh)
3877        __(andb $tagmask,%imm0_bh)
3878        __(cmpb %imm0_bh,%imm0_b)
3879        __(jne 2f)
3880        __(extract_subtag(%arg_y,%imm0_b))
3881        __(extract_subtag(%arg_z,%imm0_bh))
3882        __(cmpb %imm0_b,%imm0_bh)
3883        __(jne 2f)
3884        __(jump_builtin(_builtin_eql,2))
38851:      __(movl $t_value,%arg_z)
3886        __(ret)
38872:      __(movl $nil_value,%arg_z)
3888        __(ret)
3889_endsubp(builtin_eql)
3890
3891_spentry(builtin_length)
3892        __(extract_fulltag(%arg_z,%imm0))
3893        __(cmpl $tag_list,%imm0)
3894        __(jz 2f)
3895        __(andl $tagmask,%imm0)
3896        __(cmpl $tag_misc,%imm0)
3897        __(jnz 8f)
3898        __(extract_subtag(%arg_z,%imm0_b))
3899        __(rcmpb(%imm0_b,$min_vector_subtag))
3900        __(jb 8f)
3901        __(je 1f)
3902        /* (simple-array * (*)) */
3903        __(movl %arg_z,%arg_y)
3904        __(vector_length(%arg_y,%arg_z))
3905        __(ret)
39061:      /* vector header */
3907        __(movl vectorH.logsize(%arg_z),%arg_z)
3908        __(ret)
39092:      /* list.  Maybe null, maybe dotted or circular. */
3910        __(movl $-fixnumone,%arg_y)
3911        __(movl %arg_z,%temp0)  /* fast pointer */
3912        __(movl %arg_z,%temp1)  /* slow pointer */
39133:      __(movb %temp0_b,%al)
3914        __(andb $fulltagmask,%al)
3915        __(addl $fixnumone,%arg_y)
3916        __(compare_reg_to_nil(%temp0))
3917        __(je 9f)
3918        __(cmpb $fulltag_cons,%al)
3919        __(jne 8f)
3920        __(movb %temp1_b,%ah)
3921        __(andb $fulltagmask,%ah)
3922        __(_cdr(%temp0,%temp0))
3923        __(testl $fixnumone,%arg_y)
3924        __(je 3b)
3925        __(cmpb $fulltag_cons,%ah)
3926        __(jne 8f)
3927        __(_cdr(%temp1,%temp1))
3928        __(cmpl %temp0,%temp1)
3929        __(jne 3b)
39308:
3931        __(jump_builtin(_builtin_length,1))
39329:
3933        __(movl %arg_y,%arg_z)
3934        __(ret)
3935_endsubp(builtin_length)
3936
3937_spentry(builtin_seqtype)
3938        __(extract_fulltag(%arg_z,%imm0))
3939        __(cmpb $fulltag_cons,%imm0_b)
3940        __(jz 1f)
3941        __(cmpb $tag_misc,%imm0_b)
3942        __(jne 2f)
3943        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3944        __(rcmpb(%imm0_b,$min_vector_subtag))
3945        __(jb 2f)
3946        __(movl $nil_value,%arg_z)
3947        __(ret)
39481:      __(movl $t_value,%arg_z)
3949        __(ret)
39502:
3951        __(jump_builtin(_builtin_seqtype,1))
3952_endsubp(builtin_seqtype)
3953
3954_spentry(builtin_assq)
3955        __(cmpl $nil_value,%arg_z)
3956        __(je 5f)
39571:      __(movl %arg_z,%imm0)
3958        __(andb $fulltagmask,%imm0_b)
3959        __(cmpb $fulltag_cons,%imm0_b)
3960        __(jne 2f)
3961        __(_car(%arg_z,%temp0))
3962        __(_cdr(%arg_z,%arg_z))
3963        __(cmpl $nil_value,%temp0)
3964        __(je 4f)
3965        __(movl %temp0,%imm0)
3966        __(andb $fulltagmask,%imm0_b)
3967        __(cmpb $fulltag_cons,%imm0_b)
3968        __(jne 3f)
3969        __(_car(%temp0,%temp1))
3970        __(cmpl %temp1,%arg_y)
3971        __(jne 4f)
3972        __(movl %temp0,%arg_z)
3973        __(ret)
39744:      __(cmpl $nil_value,%arg_z)
39755:      __(jnz 1b)
3976        __(repret)
39772:      __(uuo_error_reg_not_list(Rarg_z))
39783:      __(uuo_error_reg_not_list(Rtemp0))
3979_endsubp(builtin_assq)
3980
3981_spentry(builtin_memq)
3982        __(cmpl $nil_value,%arg_z)
3983        __(jmp 3f)
39841:      __(movb $fulltagmask,%imm0_b)
3985        __(andb %arg_z_b,%imm0_b)
3986        __(cmpb $fulltag_cons,%imm0_b)
3987        __(jne 2f)
3988        __(_car(%arg_z,%temp1))
3989        __(_cdr(%arg_z,%temp0))
3990        __(cmpl %temp1,%arg_y)
3991        __(jz 4f)
3992        __(cmpl $nil_value,%temp0)
3993        __(movl %temp0,%arg_z)
39943:      __(jnz 1b)
39954:      __(repret)
39962:      __(uuo_error_reg_not_list(Rarg_z))
3997_endsubp(builtin_memq)
3998
3999logbitp_max_bit = 30
4000
4001_spentry(builtin_logbitp)
4002        /* Call out unless: both args fixnums, arg_y in `0, logbitp_max_bit) */
4003        __(movl %arg_z,%imm0)
4004        __(orl %arg_y,%imm0)
4005        __(testb $fixnummask,%imm0_b)
4006        __(jnz 1f)
4007        __(unbox_fixnum(%arg_y,%imm0))
4008        __(js 1f)       /* bit number negative */
4009        __(addb $fixnumshift,%imm0_b)
4010        __(cmpl $logbitp_max_bit<<fixnumshift,%arg_y)
4011        __(jb 2f)
4012        __(movl $logbitp_max_bit-1+fixnumshift,%imm0)
40132:      __(bt %imm0,%arg_z)
4014        __(condition_to_boolean(b,%imm0,%arg_z))
4015        __(ret)
40161:      __(jump_builtin(_builtin_logbitp,2))
4017_endsubp(builtin_logbitp)
4018
4019_spentry(builtin_logior)
4020        __(movl %arg_y,%imm0)
4021        __(orb %arg_z_b,%imm0_b)
4022        __(testb $fixnummask,%imm0_b)
4023        __(jne 1f)
4024        __(orl %arg_y,%arg_z)
4025        __(ret)
40261:
4027        __(jump_builtin(_builtin_logior,2))
4028_endsubp(builtin_logior)
4029
4030_spentry(builtin_logand)
4031        __(movl %arg_y,%imm0)
4032        __(orb %arg_z_b,%imm0_b)
4033        __(testb $fixnummask,%imm0_b)
4034        __(jne 1f)
4035        __(andl %arg_y,%arg_z)
4036        __(ret)
40371:
4038        __(jump_builtin(_builtin_logand,2))
4039_endsubp(builtin_logand)
4040
4041_spentry(builtin_negate)
4042        __(testb $fixnummask,%arg_z_b)
4043        __(jne 1f)
4044        __(negl %arg_z)
4045        __(jo C(fix_one_bit_overflow))
4046        __(repret)
40471:
4048        __(jump_builtin(_builtin_negate,1))
4049_endsubp(builtin_negate)
4050
4051_spentry(builtin_logxor)
4052        __(movl %arg_y,%imm0)
4053        __(orb %arg_z_b,%imm0_b)
4054        __(testb $fixnummask,%imm0_b)
4055        __(jne 1f)
4056        __(xorl %arg_y,%arg_z)
4057        __(ret)
40581:
4059        __(jump_builtin(_builtin_logxor,2))
4060_endsubp(builtin_logxor)
4061
4062/* temp0 = vector, arg_y = index, arg_z = newval */
4063_spentry(aset1)
4064        __(extract_typecode(%temp0,%imm0))
4065        __(box_fixnum(%imm0,%temp1))
4066        __(cmpb $min_vector_subtag,%imm0_b)
4067        __(ja _SPsubtag_misc_set)
4068        /* push frame... */
4069        __(pop %temp1)
4070        __(push $reserved_frame_marker)
4071        __(push $reserved_frame_marker)
4072        __(push %temp0)
4073        __(push %temp1)
4074        /* and fall through... */
4075_endsubp(aset1)
4076
4077_spentry(builtin_aset1)
4078        __(jump_builtin(_builtin_aset1,3))
4079_endsubp(builtin_aset1)
4080
4081_spentry(builtin_ash)
4082        __(movl %arg_y,%imm0)
4083        __(orb %arg_z_b,%imm0_b)
4084        __(testb $fixnummask,%imm0_b)
4085        __(jne 9f)
4086        __(unbox_fixnum(%arg_z,%imm0))
4087        /* Z flag set if zero ASH shift count */
4088        __(jnz 1f)
4089        __(movl %arg_y,%arg_z) /* shift by 0 */
4090        __(ret)
40911:      __(jns 3f)
4092        __(rcmpl(%imm0,$-31))
4093        __(jg 2f)
4094        __(unbox_fixnum(%arg_y,%imm0))
4095        __(sar $31,%imm0)
4096        __(box_fixnum(%imm0,%arg_z))
4097        __(ret)
40982:      /* Right-shift by small fixnum */
4099        __(negb %imm0_b)
4100        __(movzbl %imm0_b,%ecx)
4101        __(unbox_fixnum(%arg_y,%imm0))
4102        __(sar %cl,%imm0)
4103        __(box_fixnum(%imm0,%arg_z))
4104        __(ret)
41053:      /* Left shift by fixnum.  We can't shift by more than 31 bits, */
4106        /* though shifting by 32 is actually easy. */
4107        __(rcmpl(%imm0,$32))
4108        __(jg 9f)
4109        __(jne 4f)
4110        /* left-shift by 32 bits exactly */
4111        __(unbox_fixnum(%arg_y,%imm0))
4112        __(movd %imm0,%mm0)
4113        __(psllq $32,%mm0)
4114        __(jmp _SPmakes64)
41154:      /* left-shift by 1..31 bits. Safe to move shift count to %cl */
4116        __(movd %imm0,%mm1)     /* shift count */
4117        __(unbox_fixnum(%arg_y,%imm0))
4118        __(movd %imm0,%mm0)
4119        __(sarl $31,%imm0)      /* propagate sign */
4120        __(movd %imm0,%mm2)
4121        __(pshufw $0x4e,%mm2,%mm2) /* swap hi/lo halves */
4122        __(por %mm2,%mm0)
4123        __(psllq %mm1,%mm0)
4124        __(jmp _SPmakes64)
41259:
4126        __(jump_builtin(_builtin_ash,2))
4127_endsubp(builtin_ash)
4128
4129_spentry(builtin_aref1)
4130        __(extract_typecode(%arg_y,%imm0))
4131        __(box_fixnum_no_flags(%imm0,%temp0))
4132        __(cmpb $min_vector_subtag,%imm0_b)
4133        __(ja _SPsubtag_misc_ref)
4134        __(jump_builtin(_builtin_aref1,2))
4135_endsubp(builtin_aref1)
4136
4137/* Maybe check the x87 tag word to see if st(0) is valid and pop it */
4138/* if so.  This might allow us to avoid having to have a priori */
4139/* knowledge of whether a foreign function returns a floating-point result. */
4140/* backlink to saved %esp, below */
4141/* arg n-1 */
4142/* arg n-2 */
4143/* ... */
4144/* arg 0 */
4145/* space for alignment */
4146/* previous %esp */
4147
4148/*
4149 * Note that we assume that the lisp registers are in the default
4150 * state here:  that is, tcr.node_regs_mask has its default value,
4151 * and the DF is clear.
4152 */
4153_spentry(ffcall)
4154LocalLabelPrefix`'ffcall:
4155        __(unbox_fixnum(%arg_z,%imm0))
4156        __(testb $fixnummask,%arg_z_b)
4157        __(je 0f)
4158        __(movl macptr.address(%arg_z),%imm0)
41590:
4160        /* Save lisp registers. */
4161        __(push %ebp)
4162        __(mov %esp,%ebp)
4163        __(push %temp0)                 
4164        __(push %temp1)                 
4165        __(push %arg_y)                 
4166        __(push %arg_z)                 
4167        __(push %fn)         
4168        __ifdef(`WIN32_ES_HACK')
4169         __(movl rcontext(tcr.linear),%ebx)
4170        __endif
4171        __(movl %esp,rcontext(tcr.save_vsp))
4172        __(movl %ebp,rcontext(tcr.save_ebp))
4173        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4174        __(movl rcontext(tcr.foreign_sp),%esp)
4175        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4176        __(emms)
4177        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4178        __(movl (%esp),%ebp)
4179LocalLabelPrefix`'ffcall_setup:
4180        __(lea 15(%esp),%ecx)
4181        __(andl $-16,%ecx)
4182        __(movl %ecx,%esp)
4183/*      __(addl $node_size,%esp) */
4184        __ifdef(`WIN32_ES_HACK')
4185         __(push %ds)
4186         __(pop %es)
4187        __endif
4188LocalLabelPrefix`'ffcall_call:
4189        __(call *%eax)
4190        __ifdef(`WIN32_ES_HACK')
4191         __(movw tcr.ldt_selector(%ebx),%rcontext_reg)
4192        __endif
4193LocalLabelPrefix`'ffcall_call_end:
4194        __(movl %ebp,%esp)
4195        __(movl %esp,rcontext(tcr.foreign_sp))
4196        /* The high word of a 64-bit result would be in %edx right now.
4197           There doesn't seem to be any other good place to put this,
4198           though %edx is often undefined at this point. */
4199        __(mov %edx,rcontext(tcr.unboxed1))
4200        __(clr %arg_z)
4201        __(clr %arg_y)
4202        __(clr %temp1)
4203        __(clr %temp0)
4204        __(clr %fn)
4205        __(pxor %fpzero,%fpzero)
4206        __(cmpb $0,C(bogus_fp_exceptions))
4207        __(je 0f)
4208        __(movl %arg_z,rcontext(tcr.ffi_exception))
4209        __(jmp 1f)
42100:
4211        __ifdef(`SSE2_MATH_LIB')
4212        __(stmxcsr rcontext(tcr.ffi_exception))
4213        __else
4214        __(fnstsw rcontext(tcr.ffi_exception))
4215        __(fnclex)
4216        __endif
4217        __(movl rcontext(tcr.save_vsp),%esp)
4218        __(movl rcontext(tcr.save_ebp),%ebp)
4219        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4220        __(pop %fn)             
4221        __(pop %arg_z)           
4222        __(pop %arg_y)           
4223        __(pop %temp1) 
4224        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4225        __(check_pending_interrupt(%temp0))
4226        __(pop %temp0)
4227        __(leave)
4228        __(ret)
4229        /* need to deal with NSExceptions and Objc-2.0 execptions */
4230_endsubp(ffcall)
4231
4232_spentry(ffcall_return_registers)
4233        __(hlt)
4234_endsubp(ffcall_return_registers)
4235
4236/* We need to reserve a frame here if (a) nothing else was already pushed
4237/* and (b) we push something (e.g., more than 2 args in the lexpr) */
4238_spentry(spread_lexprz)
4239        new_local_labels()
4240        __(movl (%arg_z),%imm0) /* lexpr count */
4241        __(leal node_size(%arg_z,%imm0),%arg_y)
4242        __(movd %arg_y,%mm1)
4243        __(test %nargs,%nargs) /* anything pushed by caller ? */
4244        __(jne 0f)              /* yes, caller has already created frame. */
4245        __(cmpl $(nargregs*node_size),%imm0) /* will we push anything ? */
4246        __(jbe 0f)
4247        __(push $reserved_frame_marker)
4248        __(push $reserved_frame_marker)
42490:      __(addl %imm0,%nargs)
4250        __(cmpl $(1*node_size),%imm0)
4251        __(ja 2f)
4252        __(je 1f)
4253        /* lexpr count was 0; vpop the args that */
4254        /* were pushed by the caller */
4255        __(test %nargs,%nargs)
4256        __(je local_label(all_args_popped))
4257        __(pop %arg_z)
4258local_label(maybe_pop_y):
4259        __(cmpl $(1*node_size),%nargs)
4260        __(je local_label(all_args_popped))
4261        __(pop %arg_y)
4262local_label(all_args_popped):   
4263        /* If all args fit in registers but some were pushed */
4264        /* by the caller, discard the reserved frame that the caller */
4265        /* pushed.         */
4266        __(cmpl %imm0,%nargs)
4267        __(je local_label(go))
4268        __(cmpl $(nargregs*node_size),%nargs)
4269        __(ja local_label(go))
4270        __(addl $(2*node_size),%esp)
4271local_label(go):
4272        __(jmp *%ra0)
4273
4274        /* lexpr count is two or more: vpush args from the lexpr until */
4275        /* we have only two left, then assign them to arg_y and arg_z */
42762:      __(cmpl $(2*node_size),%imm0)
4277        __(je local_label(push_loop_end))
4278local_label(push_loop):
4279        __(lea -1*node_size(%imm0),%imm0)
4280        __(push -node_size(%arg_y))
4281        __(lea -1*node_size(%arg_y),%arg_y)
4282        __(cmpl $(2*node_size),%imm0)
4283        __(jne 2b)
4284local_label(push_loop_end):
4285        __(movl -node_size*2(%arg_y),%arg_z)
4286        __(movl -node_size*1(%arg_y),%arg_y)
4287        __(jmp *%ra0)
4288        /* lexpr count is one: set arg_z from the lexpr, */
4289        /* maybe vpop arg_y  */
42901:      __(movl -node_size*1(%arg_y),%arg_z)
4291        __(jmp local_label(maybe_pop_y))
4292_endsubp(spread_lexprz)
4293
4294_spentry(callback)
4295        __(push %ebp)
4296        __(movl %esp,%ebp)
4297        /* C scalar args are already on the stack. */
4298        /* arg word 0 at 8(%ebp), word 1 at 12(%ebp), etc. */
4299
4300        /* %eax is passed to us via the callback trampoline.
4301           bits 0-22: callback index
4302           bit 23: flag, set if we need to discard hidden arg on return
4303                   (ignored when upper 8 bits are non-zero)
4304           bits 24-31: arg words to discard on return (_stdcall for win32) */
4305       
4306        /* Reserve some space for results, relative to the
4307           current %ebp.  We may need quite a bit of it. */
4308        __(subl $20,%esp)
4309        __(movl $0,-16(%ebp)) /* No FP result */
4310        __(btl $23,%eax)      /* set CF if we need to discard hidden arg */
4311        __(pushfl)            /* and save for later */
4312        __(movl %eax,%ecx)    /* extract args-discard count */
4313        __(shrl $24,%ecx)
4314        __(andl $0x007fffff,%eax) /* callback index */
4315        __(movl %ecx,-20(%ebp))
4316        /* If the C stack is 16-byte aligned by convention,
4317           it should still be, and this'll be a NOP. */
4318        __(andl $~15,%esp)
4319        /* C NVRs */
4320        __(push %edi)
4321        __(push %esi)
4322        __(push %ebx)
4323        __(push %ebp)
4324        __(box_fixnum(%eax,%esi))       /* put callback index in arg_y */
4325        __(cmpb $0,C(rcontext_readonly))
4326        __(jne 0f)
4327        __(ref_global(get_tcr,%eax))
4328        __(subl $12,%esp)               /* alignment */
4329        __(push $1)                     /* stack now 16-byte aligned */
4330        __(call *%eax)
4331        __(addl $16,%esp)               /* discard arg, alignment words */
4332        /* linear TCR addr now in %eax */
4333        ifdef(`WINDOWS',`
4334        ',`
4335        __(movw tcr.ldt_selector(%eax), %rcontext_reg)
4336        ')
43370:     
4338
4339        /* ebp is 16-byte aligned, and we've pushed 4 words.  Make
4340          sure that when we push old foreign_sp, %esp will be 16-byte
4341          aligned again */
4342        __(subl $8,%esp)
4343        __(pushl rcontext(tcr.save_ebp))  /* mark cstack frame's "owner" */
4344        __(push rcontext(tcr.foreign_sp))
4345        __(movl %esp,rcontext(tcr.foreign_sp))
4346        __(clr %arg_z)
4347        /* arg_y contains callback index */
4348        __(clr %temp1)
4349        __(clr %temp0)
4350        __(clr %fn)
4351        __(pxor %fpzero,%fpzero)
4352        __(movl rcontext(tcr.save_vsp),%esp)
4353        __(movl %ebp,%arg_z)
4354        __(movl rcontext(tcr.save_ebp),%ebp)
4355        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4356        __(stmxcsr rcontext(tcr.foreign_mxcsr))
4357        __(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
4358        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4359        __(movl $nrs.callbacks,%fname)
4360        __(check_cstack_alignment())
4361        __(push $local_label(back_from_callback))
4362        __(set_nargs(2))
4363        __(jump_fname())
4364__(tra(local_label(back_from_callback)))
4365        __(movl %esp,rcontext(tcr.save_vsp))
4366        __(movl %ebp,rcontext(tcr.save_ebp))
4367        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4368        __(movl rcontext(tcr.foreign_sp),%esp)
4369        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4370        __(emms)
4371        __(pop rcontext(tcr.foreign_sp))
4372        __(addl $12,%esp)       /* discard alignment padding */
4373        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4374        __ifdef(`WIN32_ES_HACK')
4375         __(push %ds)
4376         __(pop %es)
4377        __endif
4378        __(pop %ebp)
4379        __(pop %ebx)
4380        __(pop %esi)
4381        __(pop %edi)
4382        __(movl -12(%ebp),%ecx) /* magic value for ObjC bridge */
4383        __(cmpb $1,-16(%ebp))
4384        __(jae 1f)
4385        __(movl -8(%ebp),%eax)
4386        __(movl -4(%ebp),%edx)
4387        __ifdef(`WIN_32')
4388         __(cmpl $0,-20(%ebp))
4389         __(jne local_label(winapi_return))
4390        __endif
4391        /* since we aligned the stack after pushing flags, we're not
4392           really sure where %esp is relative to where flags were saved.
4393           We do know where the saved flags are relative to %ebp, so use
4394           that to establish %esp before the popfl.
4395        */
4396        __(lea -24(%ebp),%esp)
4397        __(popfl)       /* flags from bt way back when */
4398        __(jc local_label(discard_first_arg))
4399        __(leave)
4400        __(ret)
44011:      __(jne 2f)
4402        /* single float return in x87 */
4403        __(flds -8(%ebp))
4404        __ifdef(`WIN_32')
4405         __(cmpl $0,-20(%ebp))
4406         __(jne local_label(winapi_return))
4407        __endif
4408        __(leave)
4409        __(ret)
44102:      /* double-float return in x87 */
4411        __(fldl -8(%ebp))
4412        __ifdef(`WIN_32')
4413         __(cmpl $0,-20(%ebp))
4414         __(jne local_label(winapi_return))
4415        __endif
4416        __(leave)
4417        __(ret)
4418        __ifdef(`WIN_32')
4419local_label(winapi_return):
4420          __(movl -20(%ebp),%ecx)
4421          __(leave)
4422         /* %ecx is non-zero and contains count of arg words to pop */
4423          __(popl -4(%esp,%ecx,4))
4424          __(leal -4(%esp,%ecx,4),%esp)
4425          __(ret)
4426        __endif
4427local_label(discard_first_arg):
4428        __(leave)
4429        __(ret $4)
4430_endsubp(callback)
4431
4432/* temp0 = array, arg_y = i, arg_z = j. Typecheck everything.
4433   We don't know whether the array is alleged to be simple or
4434   not, and don't know anythng about the element type.  */
4435
4436_spentry(aref2)
4437        __(testl $fixnummask,%arg_y)
4438        __(jne 0f)
4439        __(testb $fixnummask,%arg_z_b)
4440        __(jne 1f)
4441        __(extract_typecode(%temp0,%imm0))
4442        __(cmpb $subtag_arrayH,%imm0_b)
4443        __(jne 2f)
4444        __(cmpl $2<<fixnumshift,arrayH.rank(%temp0))
4445        __(jne 2f)
4446        __(cmpl arrayH.dim0(%temp0),%arg_y)
4447        __(jae 3f)
4448        __(movl arrayH.dim0+node_size(%temp0),%imm0)
4449        __(cmpl %imm0,%arg_z)
4450        __(jae 4f)
4451        __(sarl $fixnumshift,%imm0)
4452        __(imull %arg_y,%imm0)
4453        __(addl %imm0,%arg_z)
4454        __(movl %temp0,%arg_y)
4455        __(xorl %temp1,%temp1)
44566:      __(addl arrayH.displacement(%arg_y),%arg_z)
4457        __(movl arrayH.data_vector(%arg_y),%arg_y)
4458        __(extract_subtag(%arg_y,%imm0_b))
4459        __(cmpb $subtag_vectorH,%imm0_b)
4460        __(ja C(misc_ref_common))
4461        __(jmp 6b)
44620:      __(uuo_error_reg_not_fixnum(Rarg_y))
44631:      __(uuo_error_reg_not_fixnum(Rarg_z))
44642:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_2d))
44653:      __(uuo_error_array_bounds(Rarg_y,Rtemp0))
44664:      __(uuo_error_array_bounds(Rarg_z,Rtemp0))
4467
4468_endsubp(aref2)
4469
4470/* Like aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = k */
4471_spentry(aref3)
4472        __(testb $fixnummask,%temp0_b)
4473        __(jne 0f)
4474        __(testl $fixnummask,%arg_y)
4475        __(jne 1f)
4476        __(testb $fixnummask,%arg_z_b)
4477        __(jne 2f)
4478        __(extract_typecode(%temp1,%imm0))
4479        __(cmpb $subtag_arrayH,%imm0_b)
4480        __(jne 3f)
4481        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4482        __(jne 3f)
4483        __(cmpl arrayH.dim0(%temp1),%temp0)
4484        __(jae 4f)
4485        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4486        __(cmpl %imm0,%arg_y)
4487        __(jae 5f)
4488        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_z)
4489        __(jae 6f)
4490        /* index computation: k + dim2 * (j + dim1 * i) */
4491        /* (plus minor fussing for fixnum scaling) */
4492        __(sarl $fixnumshift,%imm0)
4493        __(imull %imm0,%temp0)
4494        __(addl %arg_y,%temp0)
4495        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4496        __(sarl $fixnumshift,%imm0)
4497        __(imull %imm0,%temp0)
4498        __(addl %temp0,%arg_z)
4499        __(movl %temp1,%arg_y)
45008:      __(addl arrayH.displacement(%arg_y),%arg_z)
4501        __(movl arrayH.data_vector(%arg_y),%arg_y)
4502        __(extract_subtag(%arg_y,%imm0_b))
4503        __(cmpb $subtag_vectorH,%imm0_b)
4504        __(ja C(misc_ref_common))
4505        __(jmp 8b)
45060:      __(uuo_error_reg_not_fixnum(Rtemp0))
45071:      __(uuo_error_reg_not_fixnum(Rarg_y))
45082:      __(uuo_error_reg_not_fixnum(Rarg_z))
45093:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
45104:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
45115:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
45126:      __(uuo_error_array_bounds(Rarg_z,Rtemp1))
4513_endsubp(aref3)
4514
4515/* As with aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = new_value */
4516_spentry(aset2)
4517        __(testb $fixnummask,%temp0_b)
4518        __(jne 0f)
4519        __(testl $fixnummask,%arg_y)
4520        __(jne 1f)
4521        __(extract_typecode(%temp1,%imm0))
4522        __(cmpb $subtag_arrayH,%imm0_b)
4523        __(jne 2f)
4524        __(cmpl $2<<fixnumshift,arrayH.rank(%temp1))
4525        __(jne 2f)
4526        __(cmpl arrayH.dim0(%temp1),%temp0)
4527        __(jae 3f)
4528        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4529        __(cmpl %imm0,%arg_y)
4530        __(jae 4f)
4531        __(sarl $fixnumshift,%imm0)
4532        __(imull %temp0,%imm0)
4533        __(addl %imm0,%arg_y)
4534        __(movl %temp1,%temp0)
4535        __(xorl %temp1,%temp1)
45366:      __(addl arrayH.displacement(%temp0),%arg_y)
4537        __(movl arrayH.data_vector(%temp0),%temp0)
4538        __(extract_subtag(%temp0,%imm0_b))
4539        __(cmpb $subtag_vectorH,%imm0_b)
4540        __(ja C(misc_set_common))
4541        __(jmp 6b)
45420:      __(uuo_error_reg_not_fixnum(Rtemp0))
45431:      __(uuo_error_reg_not_fixnum(Rarg_y))
45442:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_2d))
45453:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
45464:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
4547_endsubp(aset2)
4548
4549/* temp1 = array, (%esp) = i, temp0 = j, arg_y = k, arg_z = newval */
4550_spentry(aset3)
4551        __(testb $fixnummask,(%esp))
4552        __(jne 0f)
4553        __(testb $fixnummask,%temp0_b)
4554        __(jne 1f)
4555        __(testl $fixnummask,%arg_y)
4556        __(jne 2f)
4557        __(extract_typecode(%temp1,%imm0))
4558        __(cmpb $subtag_arrayH,%imm0_b)
4559        __(jne 3f)
4560        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4561        __(jne 3f)
4562        __(movl arrayH.dim0(%temp1),%imm0)
4563        __(cmpl %imm0,(%esp))   /* i on stack */
4564        __(jae 4f)
4565        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4566        __(cmpl %imm0,%temp0)
4567        __(jae 5f)
4568        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_y)
4569        __(jae 6f)
4570        /* index computation: k + dim2 * (j + dim1 * i) */
4571        /* (plus minor fussing for fixnum scaling) */
4572        __(sarl $fixnumshift,%imm0)
4573        __(imull (%esp),%imm0)  /* i on stack */
4574        __(addl %imm0,%temp0)
4575        __(addl $node_size,%esp)
4576        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4577        __(sarl $fixnumshift,%imm0)
4578        __(imull %imm0,%temp0)
4579        __(addl %temp0,%arg_y)
4580        __(movl %temp1,%temp0)
45818:      __(addl arrayH.displacement(%temp0),%arg_y)
4582        __(movl arrayH.data_vector(%temp0),%temp0)
4583        __(extract_subtag(%temp0,%imm0_b))
4584        __(cmpb $subtag_vectorH,%imm0_b)
4585        __(ja C(misc_set_common))
4586        __(jmp 8b)
45870:      __(pop %temp0)  /* supplied i */
4588        __(uuo_error_reg_not_fixnum(Rtemp0))
45891:      __(uuo_error_reg_not_fixnum(Rtemp0))
45902:      __(uuo_error_reg_not_fixnum(Rarg_y))
45913:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
45924:      __(pop %imm0)   /* supplied i is on stack */
4593        __(uuo_error_array_bounds(Rimm0,Rtemp1))
45945:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
45956:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
4596_endsubp(aset3)
4597
4598/* Prepend all but the first seven (6 words of code & other immediate data,
4599/* plus inner fn) and last (lfbits) elements of %fn to the "arglist". */
4600_spentry(call_closure)
4601        new_local_labels()
4602        __(vector_length(%fn,%imm0))
4603        __(subl $8<<fixnumshift,%imm0)  /* imm0 = inherited arg count */
4604        __(lea (%nargs,%imm0),%temp0)
4605        __(cmpl $nargregs<<fixnumshift,%temp0)
4606        __(jna local_label(regs_only))  /* either: 1 arg, 1 inherited, or */
4607                                        /* no args, 2 inherited */
4608        __(pop rcontext(tcr.save0))             /* save return address */
4609        __(cmpl $nargregs<<fixnumshift,%nargs)
4610        __(jna local_label(no_insert))
4611
4612/* Some arguments have already been pushed.  Push %imm0's worth */
4613/* of NILs, copy those arguments that have already been vpushed from */
4614/* the old TOS to the new, then insert all of the inherited args */
4615/* and go to the function. */
4616
4617        __(mov %imm0,%temp0)
4618local_label(push_nil_loop):
4619        __(push $nil_value)
4620        __(sub $fixnumone,%temp0)
4621        __(jne local_label(push_nil_loop))
4622
4623/* Need to use arg regs as temporaries.  Stash them in the spill area. */
4624        __(movl %arg_y,rcontext(tcr.save1))
4625        __(movl %arg_z,rcontext(tcr.save2))
4626
4627        __(leal (%esp,%imm0),%temp0)    /* start of already-pushed args */
4628        __(leal -nargregs<<fixnumshift(%nargs),%arg_y) /* args pushed */
4629        __(movd %imm0,%mm0)     /* save inherited arg count */
4630        __(xorl %imm0,%imm0)
4631local_label(copy_already_loop):
4632        __(movl (%temp0,%imm0),%arg_z)
4633        __(movl %arg_z,(%esp,%imm0))
4634        __(addl $fixnumone,%imm0)
4635        __(cmpl %imm0,%arg_y)
4636        __(jne local_label(copy_already_loop))
4637
4638        __(lea -node_size(%temp0,%imm0),%arg_y) /* start of args on stack */
4639        __(movl $7<<fixnumshift,%temp0) /* skip code, new fn */
4640        __(movd %mm0,%imm0)
4641local_label(insert_loop):
4642        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4643        __(addl $node_size,%temp0)
4644        __(addl $fixnumone,%nargs)
4645        __(movl %arg_z,(%arg_y))
4646        __(subl $node_size,%arg_y)
4647        __(subl $fixnumone,%imm0)
4648        __(jne local_label(insert_loop))
4649
4650        /* Recover arg regs, saved earlier */
4651        __(movl rcontext(tcr.save1),%arg_y)
4652        __(movl rcontext(tcr.save2),%arg_z)
4653        __(jmp local_label(go))
4654       
4655/* Here if no args were pushed by the caller. */
4656/* cases: */
4657/* no args, more than two inherited args */
4658/* a single arg in arg_z, more than one inherited arg */
4659/* two args in arg_y and arg_z, some number of inherited args */
4660
4661/* Therefore, we're always going to have to push something (the sum of */
4662/* %nargs and %imm0 will always be greater than $nargregs), and */
4663/* we will have to reserve space for a stack frame. */
4664/* The 0 args, 2 inherited case and the 1 arg, 1 inherited case get */
4665/* handled at local_label(regs_ony). */
4666       
4667local_label(no_insert):
4668        /* Reserve space for a stack frame */
4669        __(push $reserved_frame_marker)
4670        __(push $reserved_frame_marker)
4671        __(lea 7<<fixnumshift(%imm0),%temp0)    /* last inherited arg */
4672        __(rcmpl(%nargs,$fixnumone))
4673        __(je local_label(set_arg_y))
4674        __(jb local_label(set_y_z))
4675        /* %nargs = $nargregs (i.e., 2), vpush remaining inherited vars. */
4676
4677local_label(vpush_remaining):
4678        __(movl $7<<fixnumshift,%temp0)
4679local_label(vpush_remaining_loop):
4680        __(push misc_data_offset(%fn,%temp0))
4681        __(add $node_size,%temp0)
4682        __(add $fixnumone,%nargs)
4683        __(sub $node_size,%imm0)
4684        __(jnz local_label(vpush_remaining_loop))
4685        __(jmp local_label(go))
4686       
4687local_label(set_arg_y):
4688        /* one arg in arg_z.  set arg_y and vpush remaining inherited args */
4689        __(subl $node_size,%temp0)
4690        __(movl misc_data_offset(%fn,%temp0),%arg_y)
4691        __(addl $fixnumone,%nargs)
4692        __(subl $fixnumone,%imm0)
4693        __(jmp local_label(vpush_remaining))
4694local_label(set_y_z):
4695        __(subl $node_size,%temp0)
4696        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4697        __(addl $fixnumone,%nargs)
4698        __(subl $fixnumone,%imm0)
4699        __(jmp local_label(set_arg_y))
4700
4701local_label(go):
4702        __(movl misc_data_offset+(6*node_size)(%fn),%fn)
4703        __(push rcontext(tcr.save0))    /* restore return addr */
4704        __(movapd %fpzero,rcontext(tcr.save0))  /* clear out spill area */
4705        __(jmp *%fn)
4706local_label(regs_only):
4707        __(lea 7<<fixnumshift(%imm0),%temp0)
4708        __(test %nargs,%nargs)
4709        __(jne local_label(one_arg))
4710        /* no args passed, two inherited args */
4711        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_z)
4712        __(cmpl $node_size,%imm0)
4713        __(je local_label(rgo))
4714        __(movl misc_data_offset-(node_size*2)(%fn,%temp0),%arg_y)
4715local_label(rgo):
4716        __(addl %imm0,%nargs)
4717        __(jmp *misc_data_offset+(6*node_size)(%fn))
4718local_label(one_arg):
4719        /* one arg was passed, so there's one inherited arg */
4720        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_y)
4721        __(jmp local_label(rgo))
4722_endsubp(call_closure)
4723
4724_spentry(poweropen_callbackX)
4725        __(hlt)
4726_endsubp(poweropen_callbackX)
4727
4728_spentry(poweropen_ffcallX)
4729        __(hlt)
4730_endsubp(poweropen_ffcallX)
4731
4732_spentry(eabi_ff_call)
4733        __(hlt)
4734_endsubp(eabi_ff_call)
4735
4736_spentry(eabi_callback)
4737        __(hlt)
4738_endsubp(eabi_callback)
4739
4740
4741/* Unused, and often not used on PPC either  */
4742_spentry(callbuiltin)
4743        __(hlt)
4744_endsubp(callbuiltin)
4745
4746_spentry(callbuiltin0)
4747        __(hlt)
4748_endsubp(callbuiltin0)
4749
4750_spentry(callbuiltin1)
4751        __(hlt)
4752_endsubp(callbuiltin1)
4753
4754_spentry(callbuiltin2)
4755        __(hlt)
4756_endsubp(callbuiltin2)
4757
4758_spentry(callbuiltin3)
4759        __(hlt)
4760_endsubp(callbuiltin3)
4761
4762_spentry(restorefullcontext)
4763        __(hlt)
4764_endsubp(restorefullcontext)
4765
4766_spentry(savecontextvsp)
4767        __(hlt)
4768_endsubp(savecontextvsp)
4769
4770_spentry(savecontext0)
4771        __(hlt)
4772_endsubp(savecontext0)
4773
4774_spentry(restorecontext)
4775        __(hlt)
4776_endsubp(restorecontext)
4777
4778_spentry(stkconsyz)
4779        __(hlt)
4780_endsubp(stkconsyz)
4781
4782_spentry(stkvcell0)
4783        __(hlt)
4784_endsubp(stkvcell0)
4785
4786_spentry(stkvcellvsp)
4787        __(hlt)
4788_endsubp(stkvcellvsp)
4789
4790_spentry(breakpoint)
4791        __(hlt)
4792_endsubp(breakpoint)
4793
4794_spentry(unused_6)
4795        __(hlt)
4796Xspentry_end:
4797_endsubp(unused_6)
4798        .data
4799        .globl C(spentry_start)
4800        .globl C(spentry_end)
4801C(spentry_start):       .long Xspentry_start
4802C(spentry_end):         .long Xspentry_end
4803       
Note: See TracBrowser for help on using the repository browser.