source: release/1.3/source/lisp-kernel/x86-spentry32.s @ 11780

Last change on this file since 11780 was 11780, checked in by rme, 11 years ago

x8632 gc/runtime bugfixes from trunk (r11748, r11752, r11754)

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