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

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

On FreeBSD, whether or not we can write to rcontext depends on whether
or not the 32-bit lisp is running on a 64-bit kernel, so check
'rcontext_readonly' and skip loading rcontext from the tcr if it's
non-zero. (On a 32-bit kernel, %fs can get clobbered sometimes.)

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