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

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

Implement SParef3 and SPaset3 (ticket:364).

File size: 155.8 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        __(je 0f)
47        __(uuo_error_reg_not_tag(Rarg_y,tag_misc))
480:      __(testb $fixnummask,%arg_z_b)
49        __(je 1f)
50        __(uuo_error_reg_not_fixnum(Rarg_z))
511:      __(movl misc_header_offset(%arg_y),%imm0)
52        __(xorb %imm0_b,%imm0_b)
53        __(shrl $num_subtag_bits-fixnumshift,%imm0)
54        __(cmpl %imm0,%arg_z)
55        __(jb 2f)
56        __(uuo_error_vector_bounds(Rarg_z,Rarg_y))
572:      __(xorl %imm0,%imm0)
58        __(movb misc_subtag_offset(%arg_y),%imm0_b)
59        /* fall through */
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        __(je 0f)
429        __(uuo_error_reg_not_tag(Rarg_y,tag_misc))
4300:      __(testb $fixnummask,%arg_z_b)
431        __(je 1f)
432        __(uuo_error_reg_not_fixnum(Rarg_z))
4331:      __(movl misc_header_offset(%arg_y),%imm0)
434        __(xorb %imm0_b,%imm0_b)
435        __(shrl $num_subtag_bits-fixnumshift,%imm0)
436        __(cmp %imm0,%arg_z)
437        __(jb 2f)
438        __(uuo_error_vector_bounds(Rarg_z,Rarg_y))
4392:      __(unbox_fixnum(%temp0,%imm0))
440        __(jmp C(misc_ref_common))
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        __(je 0f)
449        __(uuo_error_reg_not_tag(Rtemp0,tag_misc))
4500:      __(mov %arg_y,%imm0)
451        __(testb $fixnummask,%imm0_b)
452        __(je 1f)
453        __(uuo_error_reg_not_fixnum(Rarg_y))
4541:      __(movl misc_header_offset(%temp0),%imm0)
455        __(xorb %imm0_b,%imm0_b)
456        __(shrl $num_subtag_bits-fixnumshift,%imm0)
457        __(cmpl %imm0,%arg_y)
458        __(jb 2f)
459        __(uuo_error_vector_bounds(Rarg_y,Rtemp0))
4602:      __(unbox_fixnum(%temp1,%imm0))
461        __(jmp C(misc_set_common))
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        __(je 0f)
470        __(uuo_error_reg_not_tag(Rtemp0,tag_misc))
4710:      __(mov %arg_y,%imm0)    /* no byte reg for %arg_y/%esi */
472        __(testb $fixnummask,%imm0_b)
473        __(je 1f)
474        __(uuo_error_reg_not_fixnum(Rarg_y))
4751:      __(movl misc_header_offset(%temp0),%imm0)
476        __(xorb %imm0_b,%imm0_b)
477        __(shrl $num_subtag_bits-fixnumshift,%imm0)
478        __(cmpl %imm0,%arg_y)
479        __(jb 2f)
480        __(uuo_error_vector_bounds(Rarg_y,Rtemp0))
4812:      __(xorl %imm0,%imm0)
482        __(movb misc_subtag_offset(%temp0),%imm0_b)
483        /* fall through */
484_endsubp(misc_set)
485
486/* imm0_b = subtag, %temp0 = vector, %arg_y = index, %arg_z = value */
487_startfn(C(misc_set_common))
488        __(movzbl %imm0_b,%imm0)
489        __(leal local_label(misc_set_jmp)(,%imm0,4),%imm0)
490        __(jmp *(%imm0))
491        .p2align 2
492local_label(misc_set_jmp):
493        /* 00-0f */
494        .long local_label(misc_set_invalid) /* 00 even_fixnum  */
495        .long local_label(misc_set_invalid) /* 01 cons  */
496        .long local_label(misc_set_invalid) /* 02 nodeheader  */
497        .long local_label(misc_set_invalid) /* 03 imm  */
498        .long local_label(misc_set_invalid) /* 04 odd_fixnum  */
499        .long local_label(misc_set_invalid) /* 05 tra  */
500        .long local_label(misc_set_invalid) /* 06 misc  */
501        .long local_label(misc_set_u32) /* 07 bignum  */
502        .long local_label(misc_set_invalid) /* 08 even_fixnum  */
503        .long local_label(misc_set_invalid) /* 09 cons  */
504        .long _SPgvset /* 0a ratio  */
505        .long local_label(misc_set_invalid) /* 0b imm  */
506        .long local_label(misc_set_invalid) /* 0c odd_fixnum  */
507        .long local_label(misc_set_invalid) /* 0d tra  */
508        .long local_label(misc_set_invalid) /* 0e misc  */
509        .long local_label(misc_set_u32) /* 0f single_float  */
510        /* 10-1f  */
511        .long local_label(misc_set_invalid) /* 10 even_fixnum  */
512        .long local_label(misc_set_invalid) /* 11 cons  */
513        .long local_label(misc_set_invalid) /* 12 nodeheader  */
514        .long local_label(misc_set_invalid) /* 13 imm  */
515        .long local_label(misc_set_invalid) /* 14 odd_fixnum  */
516        .long local_label(misc_set_invalid) /* 15 tra  */
517        .long local_label(misc_set_invalid) /* 16 misc  */
518        .long local_label(misc_set_u32) /* 17 double_float  */
519        .long local_label(misc_set_invalid) /* 18 even_fixnum  */
520        .long local_label(misc_set_invalid) /* 19 cons  */
521        .long _SPgvset /* 1a complex  */
522        .long local_label(misc_set_invalid) /* 1b imm  */
523        .long local_label(misc_set_invalid) /* 1c odd_fixnum  */
524        .long local_label(misc_set_invalid) /* 1d tra  */
525        .long local_label(misc_set_invalid) /* 1e misc  */
526        .long local_label(misc_set_u32) /* 1f macptr  */
527        /* 20-2f  */
528        .long local_label(misc_set_invalid) /* 20 even_fixnum  */
529        .long local_label(misc_set_invalid) /* 21 cons  */
530        .long local_label(misc_set_invalid) /* 22 catch_frame  */
531        .long local_label(misc_set_invalid) /* 23 imm  */
532        .long local_label(misc_set_invalid) /* 24 odd_fixnum  */
533        .long local_label(misc_set_invalid) /* 25 tra  */
534        .long local_label(misc_set_invalid) /* 26 misc  */
535        .long local_label(misc_set_u32) /* 27 dead_macptr  */
536        .long local_label(misc_set_invalid) /* 28 even_fixnum  */
537        .long local_label(misc_set_invalid) /* 29 cons  */
538        .long local_label(misc_set_function) /* 2a function  */
539        .long local_label(misc_set_invalid) /* 2b imm  */
540        .long local_label(misc_set_invalid) /* 2c odd_fixnum  */
541        .long local_label(misc_set_invalid) /* 2d tra  */
542        .long local_label(misc_set_invalid) /* 2e misc  */
543        .long local_label(misc_set_invalid) /* 2f immheader  */
544        /* 30-3f  */
545        .long local_label(misc_set_invalid) /* 30 even_fixnum  */
546        .long local_label(misc_set_invalid) /* 31 cons  */
547        .long local_label(misc_set_invalid) /* 32 nodeheader  */
548        .long local_label(misc_set_invalid) /* 33 imm  */
549        .long local_label(misc_set_invalid) /* 34 odd_fixnum  */
550        .long local_label(misc_set_invalid) /* 35 tra  */
551        .long local_label(misc_set_invalid) /* 36 misc  */
552        .long local_label(misc_set_invalid) /* 37 immheader  */
553        .long local_label(misc_set_invalid) /* 38 even_fixnum  */
554        .long local_label(misc_set_invalid) /* 39 cons  */
555        .long _SPgvset /* 3a symbol  */
556        .long local_label(misc_set_invalid) /* 3b imm  */
557        .long local_label(misc_set_invalid) /* 3c odd_fixnum  */
558        .long local_label(misc_set_invalid) /* 3d tra  */
559        .long local_label(misc_set_invalid) /* 3e misc  */
560        .long local_label(misc_set_u32) /* 3f xcode_vector  */
561        /* 40-4f  */
562        .long local_label(misc_set_invalid) /* 40 even_fixnum  */
563        .long local_label(misc_set_invalid) /* 41 cons  */
564        .long _SPgvset /* 42 lock  */
565        .long local_label(misc_set_invalid) /* 43 imm  */
566        .long local_label(misc_set_invalid) /* 44 odd_fixnum  */
567        .long local_label(misc_set_invalid) /* 45 tra  */
568        .long local_label(misc_set_invalid) /* 46 misc  */
569        .long local_label(misc_set_invalid) /* 47 immheader  */
570        .long local_label(misc_set_invalid) /* 48 even_fixnum  */
571        .long local_label(misc_set_invalid) /* 49 cons  */
572        .long _SPgvset /* 4a hash_vector  */
573        .long local_label(misc_set_invalid) /* 4b imm  */
574        .long local_label(misc_set_invalid) /* 4c odd_fixnum  */
575        .long local_label(misc_set_invalid) /* 4d tra  */
576        .long local_label(misc_set_invalid) /* 4e misc  */
577        .long local_label(misc_set_invalid) /* 4f immheader  */
578        /* 50-5f  */
579        .long local_label(misc_set_invalid) /* 50 even_fixnum  */
580        .long local_label(misc_set_invalid) /* 51 cons  */
581        .long _SPgvset /* 52 pool  */
582        .long local_label(misc_set_invalid) /* 53 imm  */
583        .long local_label(misc_set_invalid) /* 54 odd_fixnum  */
584        .long local_label(misc_set_invalid) /* 55 tra  */
585        .long local_label(misc_set_invalid) /* 56 misc  */
586        .long local_label(misc_set_invalid) /* 57 immheader  */
587        .long local_label(misc_set_invalid) /* 58 even_fixnum  */
588        .long local_label(misc_set_invalid) /* 59 cons  */
589        .long _SPgvset /* 5a weak  */
590        .long local_label(misc_set_invalid) /* 5b imm  */
591        .long local_label(misc_set_invalid) /* 5c odd_fixnum  */
592        .long local_label(misc_set_invalid) /* 5d tra  */
593        .long local_label(misc_set_invalid) /* 5e misc  */
594        .long local_label(misc_set_invalid) /* 5f immheader  */
595        /* 60-6f  */
596        .long local_label(misc_set_invalid) /* 60 even_fixnum  */
597        .long local_label(misc_set_invalid) /* 61 cons  */
598        .long _SPgvset /* 62 package  */
599        .long local_label(misc_set_invalid) /* 63 imm  */
600        .long local_label(misc_set_invalid) /* 64 odd_fixnum  */
601        .long local_label(misc_set_invalid) /* 65 tra  */
602        .long local_label(misc_set_invalid) /* 66 misc  */
603        .long local_label(misc_set_invalid) /* 67 immheader  */
604        .long local_label(misc_set_invalid) /* 68 even_fixnum  */
605        .long local_label(misc_set_invalid) /* 69 cons  */
606        .long _SPgvset /* 6a slot_vector  */
607        .long local_label(misc_set_invalid) /* 6b imm  */
608        .long local_label(misc_set_invalid) /* 6c odd_fixnum  */
609        .long local_label(misc_set_invalid) /* 6d tra  */
610        .long local_label(misc_set_invalid) /* 6e misc  */
611        .long local_label(misc_set_invalid) /* 6f immheader  */
612        /* 70-7f  */
613        .long local_label(misc_set_invalid) /* 70 even_fixnum  */
614        .long local_label(misc_set_invalid) /* 71 cons  */
615        .long _SPgvset /* 72 instance  */
616        .long local_label(misc_set_invalid) /* 73 imm  */
617        .long local_label(misc_set_invalid) /* 74 odd_fixnum  */
618        .long local_label(misc_set_invalid) /* 75 tra  */
619        .long local_label(misc_set_invalid) /* 76 misc  */
620        .long local_label(misc_set_invalid) /* 77 immheader  */
621        .long local_label(misc_set_invalid) /* 78 even_fixnum  */
622        .long local_label(misc_set_invalid) /* 79 cons  */
623        .long _SPgvset /* 7a struct  */
624        .long local_label(misc_set_invalid) /* 7b imm  */
625        .long local_label(misc_set_invalid) /* 7c odd_fixnum  */
626        .long local_label(misc_set_invalid) /* 7d tra  */
627        .long local_label(misc_set_invalid) /* 7e misc  */
628        .long local_label(misc_set_invalid) /* 7f immheader  */
629        /* 80-8f  */
630        .long local_label(misc_set_invalid) /* 80 even_fixnum  */
631        .long local_label(misc_set_invalid) /* 81 cons  */
632        .long _SPgvset /* 82 istruct  */
633        .long local_label(misc_set_invalid) /* 83 imm  */
634        .long local_label(misc_set_invalid) /* 84 odd_fixnum  */
635        .long local_label(misc_set_invalid) /* 85 tra  */
636        .long local_label(misc_set_invalid) /* 86 misc  */
637        .long local_label(misc_set_invalid) /* 87 immheader  */
638        .long local_label(misc_set_invalid) /* 88 even_fixnum  */
639        .long local_label(misc_set_invalid) /* 89 cons  */
640        .long _SPgvset /* 8a value_cell  */
641        .long local_label(misc_set_invalid) /* 8b imm  */
642        .long local_label(misc_set_invalid) /* 8c odd_fixnum  */
643        .long local_label(misc_set_invalid) /* 8d tra  */
644        .long local_label(misc_set_invalid) /* 8e misc  */
645        .long local_label(misc_set_invalid) /* 8f immheader  */
646        /* 90-9f  */
647        .long local_label(misc_set_invalid) /* 90 even_fixnum  */
648        .long local_label(misc_set_invalid) /* 91 cons  */
649        .long _SPgvset /* 92 xfunction  */
650        .long local_label(misc_set_invalid) /* 93 imm  */
651        .long local_label(misc_set_invalid) /* 94 odd_fixnum  */
652        .long local_label(misc_set_invalid) /* 95 tra  */
653        .long local_label(misc_set_invalid) /* 96 misc  */
654        .long local_label(misc_set_invalid) /* 97 immheader  */
655        .long local_label(misc_set_invalid) /* 98 even_fixnum  */
656        .long local_label(misc_set_invalid) /* 99 cons  */
657        .long _SPgvset /* 9a arrayH  */
658        .long local_label(misc_set_invalid) /* 9b imm  */
659        .long local_label(misc_set_invalid) /* 9c odd_fixnum  */
660        .long local_label(misc_set_invalid) /* 9d tra  */
661        .long local_label(misc_set_invalid) /* 9e misc  */
662        .long local_label(misc_set_invalid) /* 9f immheader  */
663        /* a0-af  */
664        .long local_label(misc_set_invalid) /* a0 even_fixnum  */
665        .long local_label(misc_set_invalid) /* a1 cons  */
666        .long _SPgvset /* a2 vectorH  */
667        .long local_label(misc_set_invalid) /* a3 imm  */
668        .long local_label(misc_set_invalid) /* a4 odd_fixnum  */
669        .long local_label(misc_set_invalid) /* a5 tra  */
670        .long local_label(misc_set_invalid) /* a6 misc  */
671        .long local_label(misc_set_single_float_vector) /* a7 sf_vector  */
672        .long local_label(misc_set_invalid) /* a8 even_fixnum  */
673        .long local_label(misc_set_invalid) /* a9 cons  */
674        .long _SPgvset /* aa simple_vector  */
675        .long local_label(misc_set_invalid) /* ab imm  */
676        .long local_label(misc_set_invalid) /* ac odd_fixnum  */
677        .long local_label(misc_set_invalid) /* ad tra  */
678        .long local_label(misc_set_invalid) /* ae misc  */
679        .long local_label(misc_set_u32) /* af u32  */
680        /* b0-bf  */
681        .long local_label(misc_set_invalid) /* b0 even_fixnum  */
682        .long local_label(misc_set_invalid) /* b1 cons  */
683        .long local_label(misc_set_invalid) /* b2 nodeheader  */
684        .long local_label(misc_set_invalid) /* b3 imm  */
685        .long local_label(misc_set_invalid) /* b4 odd_fixnum  */
686        .long local_label(misc_set_invalid) /* b5 tra  */
687        .long local_label(misc_set_invalid) /* b6 misc  */
688        .long local_label(misc_set_s32) /* b7 s32  */
689        .long local_label(misc_set_invalid) /* b8 even_fixnum  */
690        .long local_label(misc_set_invalid) /* b9 cons  */
691        .long local_label(misc_set_invalid) /* ba nodeheader  */
692        .long local_label(misc_set_invalid) /* bb imm  */
693        .long local_label(misc_set_invalid) /* bc odd_fixnum  */
694        .long local_label(misc_set_invalid) /* bd tra  */
695        .long local_label(misc_set_invalid) /* be misc  */
696        .long local_label(misc_set_fixnum_vector) /* bf fixnum_vector  */
697        /* c0-cf  */
698        .long local_label(misc_set_invalid) /* c0 even_fixnum  */
699        .long local_label(misc_set_invalid) /* c1 cons  */
700        .long local_label(misc_set_invalid) /* c2 nodeheader  */
701        .long local_label(misc_set_invalid) /* c3 imm  */
702        .long local_label(misc_set_invalid) /* c4 odd_fixnum  */
703        .long local_label(misc_set_invalid) /* c5 tra  */
704        .long local_label(misc_set_invalid) /* c6 misc  */
705        .long local_label(misc_set_string) /* c7 simple_base_string  */
706        .long local_label(misc_set_invalid) /* c8 even_fixnum  */
707        .long local_label(misc_set_invalid) /* c9 cons  */
708        .long local_label(misc_set_invalid) /* ca nodeheader  */
709        .long local_label(misc_set_invalid) /* cb imm  */
710        .long local_label(misc_set_invalid) /* cc odd_fixnum  */
711        .long local_label(misc_set_invalid) /* cd tra  */
712        .long local_label(misc_set_invalid) /* ce misc  */
713        .long local_label(misc_set_u8) /* cf u8  */
714        /* d0-df  */
715        .long local_label(misc_set_invalid) /* d0 even_fixnum  */
716        .long local_label(misc_set_invalid) /* d1 cons  */
717        .long local_label(misc_set_invalid) /* d2 nodeheader  */
718        .long local_label(misc_set_invalid) /* d3 imm  */
719        .long local_label(misc_set_invalid) /* d4 odd_fixnum  */
720        .long local_label(misc_set_invalid) /* d5 tra  */
721        .long local_label(misc_set_invalid) /* d6 misc  */
722        .long local_label(misc_set_s8)      /* d7 s8  */
723        .long local_label(misc_set_invalid) /* d8 even_fixnum  */
724        .long local_label(misc_set_invalid) /* d9 cons  */
725        .long local_label(misc_set_invalid) /* da nodeheader  */
726        .long local_label(misc_set_invalid) /* db imm  */
727        .long local_label(misc_set_invalid) /* dc odd_fixnum  */
728        .long local_label(misc_set_invalid) /* dd tra  */
729        .long local_label(misc_set_invalid) /* de misc  */
730        .long local_label(misc_set_invalid) /* df immheader  */
731        /* e0-ef  */
732        .long local_label(misc_set_invalid) /* e0 even_fixnum  */
733        .long local_label(misc_set_invalid) /* e1 cons  */
734        .long local_label(misc_set_invalid) /* e2 nodeheader  */
735        .long local_label(misc_set_invalid) /* e3 imm  */
736        .long local_label(misc_set_invalid) /* e4 odd_fixnum  */
737        .long local_label(misc_set_invalid) /* e5 tra  */
738        .long local_label(misc_set_invalid) /* e6 misc  */
739        .long local_label(misc_set_u16) /* e7 u16  */
740        .long local_label(misc_set_invalid) /* e8 even_fixnum  */
741        .long local_label(misc_set_invalid) /* e9 cons  */
742        .long local_label(misc_set_invalid) /* ea nodeheader  */
743        .long local_label(misc_set_invalid) /* eb imm  */
744        .long local_label(misc_set_invalid) /* ec odd_fixnum  */
745        .long local_label(misc_set_invalid) /* ed tra  */
746        .long local_label(misc_set_invalid) /* ee misc  */
747        .long local_label(misc_set_s16) /* ef s16  */
748        /* f0-ff  */
749        .long local_label(misc_set_invalid) /* f0 even_fixnum  */
750        .long local_label(misc_set_invalid) /* f1 cons  */
751        .long local_label(misc_set_invalid) /* f2 nodeheader  */
752        .long local_label(misc_set_invalid) /* f3 imm  */
753        .long local_label(misc_set_invalid) /* f4 odd_fixnum  */
754        .long local_label(misc_set_invalid) /* f5 tra  */
755        .long local_label(misc_set_invalid) /* f6 misc  */
756        .long local_label(misc_set_double_float_vector) /* f7 df vector  */
757        .long local_label(misc_set_invalid) /* f8 even_fixnum  */
758        .long local_label(misc_set_invalid) /* f9 cons  */
759        .long local_label(misc_set_invalid) /* fa nodeheader  */
760        .long local_label(misc_set_invalid) /* fb imm  */
761        .long local_label(misc_set_invalid) /* fc odd_fixnum  */
762        .long local_label(misc_set_invalid) /* fd tra  */
763        .long local_label(misc_set_invalid) /* fe misc  */
764        .long local_label(misc_set_bit_vector) /* ff bit_vector  */
765
766local_label(misc_set_function):
767        /* Functions are funny: the first N words are treated as */
768        /* (UNSIGNED-BYTE 32), where N is the low 16 bits of the first word. */
769        __(movzwl misc_data_offset(%temp0),%imm0)
770        __(shl $fixnumshift,%imm0)
771        __(rcmpl(%arg_y,%imm0))
772        __(jae _SPgvset)
773local_label(misc_set_u32):
774        /* Either a non-negative fixnum, a positive one-digit bignum, or */
775        /* a two-digit bignum whose sign-digit is 0 is OK. */
776        __(movl $~(target_most_positive_fixnum <<fixnumshift),%imm0)
777        __(test %arg_z,%imm0)
778        __(movl %arg_z,%imm0)
779        __(jne 1f)
780        __(sarl $fixnumshift,%imm0)
781        __(jmp 9f)
7821:      __(andb $tagmask,%imm0_b)
783        __(cmpb $tag_misc,%imm0_b)
784        __(jne local_label(misc_set_bad))
785        __(movb misc_subtag_offset(%arg_z),%imm0_b)
786        __(cmpb $subtag_bignum,%imm0_b)
787        __(jne local_label(misc_set_bad))
788        __(movl misc_header_offset(%arg_z),%imm0)
789        __(cmpl $two_digit_bignum_header,%imm0)
790        __(je 3f)
791        __(cmpl $one_digit_bignum_header,%imm0)
792        __(jne local_label(misc_set_bad))
793        __(movl misc_data_offset(%arg_z),%imm0)
794        __(testl %imm0,%imm0)
795        __(js local_label(misc_set_bad))
796        __(jmp 9f)
7973:      __(movl misc_data_offset(%arg_z),%imm0)
798        __(cmpl $0,misc_data_offset+4(%arg_z))
799        __(jne local_label(misc_set_bad))
8009:      __(movl %imm0,misc_data_offset(%temp0,%arg_y))
801        __(ret)
802local_label(misc_set_s32):
803        __(unbox_fixnum(%arg_z,%imm0))
804        __(testb $fixnummask,%arg_z_b)
805        __(je 9f)
8061:      __(movb %arg_z_b,%imm0_b)
807        __(andb $tagmask,%imm0_b)
808        __(cmpb $tag_misc,%imm0_b)
809        __(jne local_label(misc_set_bad))
810        __(movl misc_header_offset(%arg_z),%imm0)
811        __(cmpl $one_digit_bignum_header,%imm0)
812        __(jne local_label(misc_set_bad))
813        __(movl misc_data_offset(%arg_z),%imm0)
8149:      __(movl %imm0,misc_data_offset(%temp0,%arg_y))
815        __(ret)
816local_label(misc_set_bad):
817        __(movl %arg_z,%arg_y)
818        __(movl %temp0,%arg_z)
819        __(push $reserved_frame_marker)
820        __(push $reserved_frame_marker)
821        __(push $XNOTELT)
822        __(set_nargs(3))
823        __(jmp _SPksignalerr)
824local_label(misc_set_single_float_vector):
825        __(extract_lisptag(%arg_z,%imm0))
826        __(cmpb $tag_misc,%imm0_b)
827        __(jne local_label(misc_set_bad))
828        __(movb misc_subtag_offset(%arg_z),%imm0_b)
829        __(cmpb $subtag_single_float,%imm0_b)
830        __(jne local_label(misc_set_bad))
831        __(movl single_float.value(%arg_z),%imm0)
832        __(movl %imm0,misc_data_offset(%temp0,%arg_y))
833        __(ret)
834local_label(misc_set_double_float_vector):
835        __(extract_lisptag(%arg_z,%imm0))
836        __(cmpb $tag_misc,%imm0_b)
837        __(jne local_label(misc_set_bad))
838        __(movb misc_subtag_offset(%arg_z),%imm0_b)
839        __(cmpb $subtag_double_float,%imm0_b)
840        __(jne local_label(misc_set_bad))
841        __(movsd double_float.value(%arg_z),%fp0)
842        __(movsd %fp0,misc_dfloat_offset(%temp0,%arg_y,2))
843        __(ret)
844local_label(misc_set_fixnum_vector):
845        __(unbox_fixnum(%arg_z,%imm0))
846        __(testb $fixnummask,%arg_z_b)
847        __(jne local_label(misc_set_bad))
848        __(movl %imm0,misc_data_offset(%temp0,%arg_y))
849        __(ret)
850local_label(misc_set_u8):
851        __(testl $~(0xff<<fixnumshift),%arg_z)
852        __(jne local_label(misc_set_bad))
853        __(unbox_fixnum(%arg_y,%imm0))
854        __(movl %arg_z,%arg_y)
855        __(shll $8-fixnumshift,%arg_z)
856        __(movb %arg_z_bh,misc_data_offset(%temp0,%imm0))
857        __(movl %arg_y,%arg_z)
858        __(ret)
859local_label(misc_set_s8):
860        __(movl %arg_z,%imm0)
861        __(shll $32-(8+fixnumshift),%imm0)
862        __(sarl $32-(8+fixnumshift),%imm0)
863        __(cmpl %arg_z,%imm0)
864        __(jne local_label(misc_set_bad))
865        __(testb $fixnummask,%arg_z_b)
866        __(jne local_label(misc_set_bad))
867        __(unbox_fixnum(%arg_y,%imm0))
868        __(movl %arg_z,%arg_z)
869        __(shll $8-fixnumshift,%arg_z)
870        __(movb %arg_z_bh,misc_data_offset(%temp0,%imm0))
871        __(movl %arg_y,%arg_z)
872        __(ret)
873local_label(misc_set_string):
874        __(cmpb $subtag_character,%arg_z_b)
875        __(jne local_label(misc_set_bad))
876        __(movl %arg_z,%imm0)
877        __(shrl $charcode_shift,%imm0)
878        __(movl %imm0,misc_data_offset(%temp0,%arg_y))
879        __(ret)
880local_label(misc_set_u16):
881        __(testl $~(0xffff<<fixnumshift),%arg_z)
882        __(jne local_label(misc_set_bad))
883        __(movl %arg_y,%imm0)
884        __(shrl $1,%imm0)
885        __(mark_as_imm(%temp1))
886        __(unbox_fixnum(%arg_z,%temp1))
887        __(movw %temp1_w,misc_data_offset(%temp0,%imm0))
888        __(mark_as_node(%temp1))
889        __(ret)
890local_label(misc_set_s16):
891        __(movl %arg_z,%imm0)
892        __(shll $32-(16+fixnumshift),%imm0)
893        __(sarl $32-(16+fixnumshift),%imm0)
894        __(cmpl %arg_z,%imm0)
895        __(jne local_label(misc_set_bad))
896        __(testb $fixnummask,%arg_z_b)
897        __(jne local_label(misc_set_bad))
898        __(movl %arg_y,%imm0)
899        __(shrl $1,%imm0)
900        __(mark_as_imm(%temp1))
901        __(unbox_fixnum(%arg_z,%temp1))
902        __(movw %temp1_w,misc_data_offset(%temp0,%imm0))
903        __(mark_as_node(%temp1))
904        __(ret)
905local_label(misc_set_bit_vector):
906        __(testl $~fixnumone,%arg_z)
907        __(jne local_label(misc_set_bad))
908        __(unbox_fixnum(%arg_y,%imm0))
909        __(testb %arg_z_b,%arg_z_b)
910        __(je local_label(misc_set_clr_bit))
911local_label(misc_set_set_bit):
912        __(btsl %imm0,misc_data_offset(%temp0))
913        __(ret)
914local_label(misc_set_clr_bit):
915        __(btrl %imm0,misc_data_offset(%temp0))
916        __(ret)
917local_label(misc_set_invalid):
918        __(push $reserved_frame_marker)
919        __(push $reserved_frame_marker)
920        __(push $XSETBADVEC)
921        __(push %temp0)
922        __(set_nargs(4))
923        __(jmp _SPksignalerr)
924_endfn(C(misc_set_common))
925
926_spentry(Fret1valn)
927        .globl C(ret1valn)
928__(tra(C(ret1valn)))
929        __(mov (%esp),%ra0)
930        __(mov %arg_z,(%esp))
931        __(set_nargs(1))
932        __(jmp *%ra0)
933_endsubp(Fret1valn)
934
935_spentry(nvalret)
936        .globl C(nvalret)
937C(nvalret):
938        __(ref_global(ret1val_addr,%temp0))
939        __(cmpl lisp_frame.savera0(%ebp),%temp0)
940        __(je 1f)
941        __(test %nargs,%nargs)
942        __(movl $nil_value,%arg_z)
943        __(cmovnel -node_size(%esp,%nargs),%arg_z)
944        __(leave)
945        __(ret)
946
947/* actually need to return values; always need to copy. */
9481:      __(lea 2*node_size(%ebp),%imm0)
949        __(pushl (%imm0))
950        __(movl 0(%ebp),%ebp)
951        __(addl $node_size,%imm0)
952        __(lea node_size(%esp,%nargs),%temp0)
953        __(xorl %arg_y,%arg_y)
954        __(jmp 3f)
9552:      __(movl -node_size(%temp0),%arg_z)
956        __(subl $node_size,%temp0)
957        __(addl $node_size,%arg_y)
958        __(movl %arg_z,-node_size(%imm0))
959        __(subl $node_size,%imm0)
9603:      __(cmpl %arg_y,%nargs)
961        __(jne 2b)
962        __(pop %ra0)
963        __(movl %imm0,%esp)
964        __(jmp *%ra0)
965_endsubp(nvalret)
966
967_spentry(jmpsym)
968        __(jump_fname())
969_endsubp(jmpsym)
970
971_spentry(jmpnfn)
972        __(mov %temp0,%fn)
973        __(jmp *%fn)
974_endsubp(jmpnfn)
975
976_spentry(funcall)
977        __(do_funcall())
978_endsubp(funcall)
979
980/* Make a lisp integer (fixnum or one-digit bignum) from the value in %imm0 */
981_spentry(makes32)
982        __(imull $fixnumone,%imm0,%arg_z)       /* result is fixnum-tagged */
983        __(jno 0f)                              /* but may have overflowed */
984        __(movd %imm0,%mm1)
985        __(movl $one_digit_bignum_header,%imm0)
986        __(movd %imm0,%mm0)
987        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
988        __(movd %mm1,misc_data_offset(%arg_z))
9890:      __(repret)
990_endsubp(makes32)
991
992/* Make a lisp integer out of the unboxed 64-bit word in %mm0. */
993/* This is a little clumsy, but the alternative requires callers to */
994/* have already marked %edx as an imm reg (or else store it in memory
995/* somewhere), and I'm nervous about */
996/* splitting up the mark-as-imm/mark-as-node between two separate */
997/* pieces of code. */
998_spentry(makes64)
999        __(movq %mm0,%mm2)
1000        __(pshufw $0x4e,%mm0,%mm1)      /* swap hi/lo halves */
1001        __(psrad $31,%mm0)      /* propagate sign */
1002        __(pcmpeqd %mm0,%mm1)   /* all ones if equal */
1003        __(movd %mm1,%imm0)
1004        __(cmpb $-1,%imm0_b)    /* upper half just sign extension? */
1005        __(jne 1f)
1006        __(movd %mm2,%imm0)
1007        __(jmp _SPmakes32)
10081:      __(movl $two_digit_bignum_header,%imm0)
1009        __(movd %imm0,%mm0)
1010        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
1011        __(movq %mm2,misc_data_offset(%arg_z))
1012        __(ret)
1013_endsubp(makes64)
1014
1015_spentry(syscall)
1016        /* Save lisp registers */
1017        __(push %ebp)
1018        __(movl %esp,%ebp)
1019        __(push %temp0)
1020        __(push %temp1)
1021        __(push %arg_y)
1022        __(push %arg_z)
1023        __(push %fn)
1024        __(movl %esp,rcontext(tcr.save_vsp))
1025        __(movl %ebp,rcontext(tcr.save_ebp))
1026        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
1027        __(movl rcontext(tcr.foreign_sp),%esp)
1028        /* preserve state of direction flag */
1029        __(pushfl)
1030        __(popl rcontext(tcr.save_eflags))
1031        __(cld)
1032        __(emms)
1033        __(pop %ebp)            /* backlink */
1034        __(lea 15(%esp),%edx)
1035        __(andl $-16,%edx)
1036        __(movl %edx,%esp)
1037        __(unbox_fixnum(%arg_z,%eax))   /* syscall number */
1038        __(movl $local_label(back_from_sysenter),%edx)
1039        __(push %edx)
1040        __(movl %esp,%ecx)
1041        __(sysenter)
1042local_label(back_from_sysenter):
1043        __(jnc 0f)
1044        __(neg %eax)
10450:     
1046        __(movl %ebp,%esp)
1047        __(movl %esp,rcontext(tcr.foreign_sp))
1048        __(clr %arg_z)
1049        __(clr %arg_y)
1050        __(clr %temp1)
1051        __(clr %temp0)
1052        __(clr %fn)
1053        __(pxor %fpzero,%fpzero)
1054        __(pushl rcontext(tcr.save_eflags))
1055        __(popfl)
1056        __(movl rcontext(tcr.save_vsp),%esp)
1057        __(movl rcontext(tcr.save_ebp),%ebp)
1058        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
1059        __(pop %fn)
1060        __(pop %arg_z)
1061        __(pop %arg_y)
1062        __(pop %temp1)
1063        __(check_pending_interrupt(%temp0))
1064        __(pop %temp0)
1065        __(leave)
1066        __(ret)
1067_endsubp(syscall)
1068
1069/* Make system call that returns a doubleword result in %edx:%eax and */
1070/* copy the result into %mm0. */
1071_spentry(syscall2)
1072        /* Save lisp registers */
1073        __(push %ebp)
1074        __(movl %esp,%ebp)
1075        __(push %temp0)
1076        __(push %temp1)
1077        __(push %arg_y)
1078        __(push %arg_z)
1079        __(push %fn)
1080        __(movl %esp,rcontext(tcr.save_vsp))
1081        __(movl %ebp,rcontext(tcr.save_ebp))
1082        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
1083        __(movl rcontext(tcr.foreign_sp),%esp)
1084        /* preserve state of direction flag */
1085        __(pushfl)
1086        __(popl rcontext(tcr.save_eflags))
1087        __(cld)
1088        __(emms)
1089        __(pop %ebp)            /* backlink */
1090        __(lea 15(%esp),%edx)
1091        __(andl $-16,%edx)
1092        __(movl %edx,%esp)
1093        __(unbox_fixnum(%arg_z,%eax))   /* syscall number */
1094        __(pushl $local_label(back_from_syscall))
1095        __(int $0x80)
1096local_label(back_from_syscall):
1097        __(jnc 0f)
1098        __(neg %eax)
1099        __(movl $-1,%edx)
11000:
1101        /* just use memory rather than screwing around with */
1102        /* movd %eax,%mm0, movd %edx,%mm1, psllq $32,%mm1, por %mm1,%mm0 */
1103        __(push %edx)
1104        __(push %eax)
1105        __(movq (%esp),%mm0)
1106        __(movl %ebp,%esp)
1107        __(movl %esp,rcontext(tcr.foreign_sp))
1108        __(clr %arg_z)
1109        __(clr %arg_y)
1110        __(clr %temp1)
1111        __(clr %temp0)
1112        __(clr %fn)
1113        __(pxor %fpzero,%fpzero)
1114        __(pushl rcontext(tcr.save_eflags))
1115        __(popf)
1116        __(movl rcontext(tcr.save_vsp),%esp)
1117        __(movl rcontext(tcr.save_ebp),%ebp)
1118        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
1119        __(pop %fn)
1120        __(pop %arg_z)
1121        __(pop %arg_y)
1122        __(pop %temp1)
1123        __(check_pending_interrupt(%temp0))
1124        __(pop %temp0)
1125        __(leave)
1126        __(ret)
1127_endsubp(syscall2)
1128
1129
1130_spentry(mkcatch1v)
1131        __(nMake_Catch(0))
1132        __(ret)
1133_endsubp(mkcatch1v)
1134
1135_spentry(mkunwind)
1136        __(movl $undefined,%arg_z)
1137        __(Make_Catch(fixnumone))
1138        __(jmp *%ra0)
1139_endsubp(mkunwind)
1140
1141/* this takes a return address in %ra0; it's "new" in that it does the */
1142/*   double binding of *interrupt-level* out-of-line */
1143_spentry(nmkunwind)
1144        __(movl rcontext(tcr.tlb_pointer),%arg_z)
1145        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_z),%arg_y)
1146        __(push %arg_y)
1147        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
1148        __(push rcontext(tcr.db_link))
1149        __(movl %esp,rcontext(tcr.db_link))
1150        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_z))
1151        __(movl $undefined,%arg_z)
1152        /* %arg_z = tag, %xfn (%temp1) = pc */
1153        __(Make_Catch(fixnumone))
1154        __(movl %arg_y,%arg_z)
1155        __(jmp _SPbind_interrupt_level)
1156_endsubp(nmkunwind)
1157
1158_spentry(mkcatchmv)
1159        __(nMake_Catch(fixnumone))
1160        __(ret)
1161_endsubp(mkcatchmv)
1162
1163_spentry(throw)
1164        __(movl rcontext(tcr.catch_top),%imm0)
1165        __(movl (%esp,%nargs),%arg_y)   /* arg_y = tag   */
1166        __(movd %nargs,%mm0)
1167        __(xorl %temp1,%temp1)
1168        __(jmp local_label(_throw_test))
1169local_label(_throw_loop):
1170        __(cmpl %arg_y,catch_frame.catch_tag(%imm0))
1171        __(je local_label(_throw_found))
1172        __(movl catch_frame.link(%imm0),%imm0)
1173        __(addl $fixnum_one,%temp1)
1174local_label(_throw_test):
1175        __(test %imm0,%imm0)
1176        __(jne local_label(_throw_loop))
1177        __(push %ra0)
1178        __(uuo_error_reg_not_tag(Rarg_y,subtag_catch_frame))
1179        __(pop %ra0)
1180        __(jmp _SPthrow)
1181local_label(_throw_found):
1182        __(testb $fulltagmask,catch_frame.mvflag(%imm0))
1183        __(movl %temp1,%imm0)
1184        __(movd %mm0,%nargs)
1185        __(jne local_label(_throw_multiple))
1186        __(movl $nil_value,%arg_z)
1187        __(test %nargs,%nargs)
1188        __(je local_label(_throw_one_value))
1189        __(movl -node_size(%esp,%nargs),%arg_z)
1190        __(add %nargs,%esp)
1191local_label(_throw_one_value):
1192        __(movl $local_label(_threw_one_value),%ra0)
1193        __(jmp _SPnthrow1value)
1194__(tra(local_label(_threw_one_value)))
1195        __(movl rcontext(tcr.catch_top),%arg_y)
1196        __(movl catch_frame.db_link(%arg_y),%imm0)
1197        __(cmpl %imm0,rcontext(tcr.db_link))
1198        __(jz local_label(_threw_one_value_dont_unbind))
1199        __(push $local_label(_threw_one_value_dont_unbind))
1200        __(jmp _SPunbind_to)    /* preserves registers */
1201__(tra(local_label(_threw_one_value_dont_unbind)))
1202        __(movl catch_frame.ebp(%arg_y),%ebp)
1203        __(movl catch_frame.foreign_sp(%arg_y),%imm0)
1204        __(movl %imm0,rcontext(tcr.foreign_sp))
1205        __(movl catch_frame.xframe(%arg_y),%imm0)
1206        __(movl %imm0,rcontext(tcr.xframe))
1207        __(movl catch_frame.esp(%arg_y),%esp)
1208        __(movl catch_frame.link(%arg_y),%imm0)
1209        __(movl %imm0,rcontext(tcr.catch_top))
1210        __(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
1211        __(movl (%imm0),%imm0)
1212        __(movl %imm0,rcontext(tcr.save_tsp))
1213        __(movl %imm0,rcontext(tcr.next_tsp))
1214        __(movl catch_frame.pc(%arg_y),%ra0)
1215        __(jmp *%ra0)
1216local_label(_throw_multiple):
1217        __(movl $local_label(_threw_multiple),%ra0)
1218        __(jmp _SPnthrowvalues)
1219__(tra(local_label(_threw_multiple)))
1220        __(movl rcontext(tcr.catch_top),%arg_y)
1221        __(movl catch_frame.db_link(%arg_y),%imm0)
1222        __(cmpl %imm0,rcontext(tcr.db_link))
1223        __(je local_label(_threw_multiple_dont_unbind))
1224        __(push $local_label(_threw_multiple_dont_unbind))
1225        __(jmp _SPunbind_to)    /* preserves registers */
1226__(tra(local_label(_threw_multiple_dont_unbind)))
1227        /* Copy multiple values from the current %esp to the target %esp   */
1228        __(lea (%esp,%nargs),%imm0)
1229        __(movd %nargs,%mm0)    /* nargs is aka temp1 */
1230        __(movl catch_frame.esp(%arg_y),%temp1)
1231        __(jmp local_label(_threw_multiple_push_test))
1232local_label(_threw_multiple_push_loop):
1233        __(subl $node_size,%imm0)
1234        __(subl $node_size,%temp1)
1235        __(movl (%imm0),%arg_z)
1236        __(movl %arg_z,(%temp1))
1237local_label(_threw_multiple_push_test):
1238        __(cmpl %imm0,%esp)
1239        __(jne local_label(_threw_multiple_push_loop))
1240        /* target %esp is now in %temp1   */
1241        __(movl catch_frame.ebp(%arg_y),%ebp)
1242        __(movl catch_frame.foreign_sp(%arg_y),%imm0)
1243        __(movl %imm0,rcontext(tcr.foreign_sp))       
1244        __(movl catch_frame.xframe(%arg_y),%imm0)
1245        __(movl %imm0,rcontext(tcr.xframe))
1246        __(movl %temp1,%esp)
1247        __(movl catch_frame.link(%arg_y),%temp1)
1248        __(movl %temp1,rcontext(tcr.catch_top))
1249        __(movd %mm0,%nargs)
1250        __(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
1251        __(movl catch_frame.pc(%arg_y),%ra0)
1252        __(movl (%imm0),%imm0)
1253        __(movl %imm0,rcontext(tcr.save_tsp))
1254        __(movl %imm0,rcontext(tcr.next_tsp))
1255        __(jmp *%ra0)
1256_endsubp(throw)
1257
1258        /* This takes N multiple values atop the vstack.   */
1259_spentry(nthrowvalues)
1260        __(movb $1,rcontext(tcr.unwinding))
1261        __(movl %ra0,rcontext(tcr.save0)) /* %ra0 (aka %temp0) to spill area */
1262local_label(_nthrowv_nextframe):
1263        __(subl $fixnumone,%imm0)
1264        __(js local_label(_nthrowv_done))
1265        __(movd %imm0,%mm1)
1266        __(movl rcontext(tcr.catch_top),%temp0)
1267        __(movl catch_frame.link(%temp0),%imm0)
1268        __(movl %imm0,rcontext(tcr.catch_top))
1269        __(movl catch_frame.db_link(%temp0),%imm0)
1270        __(cmpl %imm0,rcontext(tcr.db_link))
1271        __(jz local_label(_nthrowv_dont_unbind))
1272        __(push %temp1)
1273        __(push %temp0)
1274        __(push $local_label(_nthrowv_back_from_unbind))
1275        __(jmp _SPunbind_to)
1276__(tra(local_label(_nthrowv_back_from_unbind)))
1277        __(pop %temp0)
1278        __(pop %temp1)
1279local_label(_nthrowv_dont_unbind):
1280        __(cmpb $unbound_marker,catch_frame.catch_tag(%temp0))
1281        __(je local_label(_nthrowv_do_unwind))
1282/* A catch frame.  If the last one, restore context from there.   */
1283        __(movd %mm1,%imm0)
1284        __(test %imm0,%imm0)    /* last catch frame ?   */
1285        __(jne local_label(_nthrowv_skip))
1286        __(movl catch_frame.xframe(%temp0),%arg_y)
1287        __(movl %arg_y,rcontext(tcr.xframe))
1288        __(lea (%esp,%nargs),%arg_y)
1289        __(movl catch_frame.esp(%temp0),%arg_z)
1290        __(movd %nargs,%mm2)
1291        __(jmp local_label(_nthrowv_push_test))
1292local_label(_nthrowv_push_loop):
1293        __(subl $node_size,%arg_y)
1294        __(subl $node_size,%arg_z)
1295        __(movd (%arg_y),%mm0)
1296        __(movd %mm0,(%arg_z))
1297local_label(_nthrowv_push_test):
1298        __(subl $node_size,%nargs)
1299        __(jns local_label(_nthrowv_push_loop))
1300        __(movd %mm2,%nargs)
1301        __(movl catch_frame.xframe(%temp0),%arg_y)
1302        __(movl %arg_y,rcontext(tcr.xframe))
1303        __(movl %arg_z,%esp)
1304        __(movl catch_frame.ebp(%temp0),%ebp)
1305        __(movd catch_frame.foreign_sp(%temp0),%stack_temp)
1306        __(movd %stack_temp,rcontext(tcr.foreign_sp))       
1307local_label(_nthrowv_skip):     
1308        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
1309        __(movl %imm0,rcontext(tcr.save_tsp))
1310        __(movl %imm0,rcontext(tcr.next_tsp))
1311        __(movd %mm1,%imm0)
1312        __(jmp local_label(_nthrowv_nextframe))
1313local_label(_nthrowv_do_unwind):       
1314/* This is harder.  Call the cleanup code with the multiple values and   */
1315/* nargs, the throw count, and the caller's return address in a temp  */
1316/* stack frame.   */
1317        __(leal (%esp,%nargs),%arg_y)
1318        __(push catch_frame.pc(%temp0))
1319        __(movl catch_frame.ebp(%temp0),%ebp)
1320        __(movd catch_frame.xframe(%temp0),%stack_temp)
1321        __(movd %stack_temp,rcontext(tcr.xframe))
1322        __(movl catch_frame.esp(%temp0),%arg_z)
1323        __(movd catch_frame.foreign_sp(%temp0),%stack_temp)
1324        __(movd %stack_temp,rcontext(tcr.foreign_sp))       
1325        /* Discard the catch frame, so we can build a temp frame   */
1326        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
1327        __(movl %imm0,rcontext(tcr.save_tsp))
1328        __(movl %imm0,rcontext(tcr.next_tsp))
1329        __(movd %temp1,%mm2) /* save %nargs */
1330        /* tsp overhead, nargs, throw count, ra0   */
1331        __(dnode_align(%nargs,(tsp_frame.fixed_overhead+(3*node_size)),%imm0))
1332        __(movl %imm0,%temp1)
1333        __(TSP_Alloc_Var(%temp1,%imm0))
1334        __(movd %mm2,%temp1) /* aka %nargs */
1335
1336        __(movl %nargs,(%imm0))
1337        __(movl rcontext(tcr.save0),%ra0)
1338        __(movl %ra0,node_size(%imm0))
1339        __(movd %mm1,node_size*2(%imm0))
1340        __(leal node_size*3(%imm0),%imm0)
1341        __(jmp local_label(_nthrowv_tpushtest))
1342local_label(_nthrowv_tpushloop):
1343        __(movl -node_size(%arg_y),%temp0)
1344        __(subl $node_size,%arg_y)
1345        __(movl %temp0,(%imm0))
1346        __(addl $node_size,%imm0)
1347local_label(_nthrowv_tpushtest):
1348        __(subl $node_size,%nargs)
1349        __(jns local_label(_nthrowv_tpushloop))
1350        __(pop %xfn)    /* aka %temp1/%nargs */
1351        __(movl %arg_z,%esp)
1352/* Ready to call cleanup code. set up tra, jmp to %xfn   */
1353        __(push $local_label(_nthrowv_called_cleanup))
1354        __(movb $0,rcontext(tcr.unwinding))
1355        __(jmp *%xfn)
1356__(tra(local_label(_nthrowv_called_cleanup)))
1357
1358        __(movb $1,rcontext(tcr.unwinding))
1359        __(movl rcontext(tcr.save_tsp),%imm0)
1360        __(movl tsp_frame.data_offset+(0*node_size)(%imm0),%nargs)
1361        __(movl tsp_frame.data_offset+(1*node_size)(%imm0),%ra0)
1362        __(movl %ra0,rcontext(tcr.save0))
1363        __(movd tsp_frame.data_offset+(2*node_size)(%imm0),%mm1)
1364        __(movd %nargs,%mm2)
1365        __(addl $tsp_frame.fixed_overhead+(node_size*3),%imm0)
1366        __(jmp local_label(_nthrowv_tpoptest))
1367local_label(_nthrowv_tpoploop):
1368        __(push (%imm0))
1369        __(addl $node_size,%imm0)
1370local_label(_nthrowv_tpoptest):
1371        __(subl $node_size,%nargs)
1372        __(jns local_label(_nthrowv_tpoploop))
1373        __(movd %mm2,%nargs)
1374        __(movl rcontext(tcr.save_tsp),%imm0)
1375        __(movl (%imm0),%imm0)
1376        __(movl %imm0,rcontext(tcr.save_tsp))
1377        __(movl %imm0,rcontext(tcr.next_tsp))
1378        __(movd %mm1,%imm0)
1379        __(jmp local_label(_nthrowv_nextframe))
1380local_label(_nthrowv_done):
1381        __(movb $0,rcontext(tcr.unwinding))
1382        __(check_pending_interrupt(%imm0))
1383local_label(_nthrowv_return):
1384        __(movl rcontext(tcr.save0),%ra0)
1385        __(movss %fpzero,rcontext(tcr.save0))
1386        __(jmp *%ra0)   
1387_endsubp(nthrowvalues)
1388
1389/* This is a (slight) optimization.  When running an unwind-protect,  */
1390/* save the single value and the throw count in the tstack frame.  */
1391/* Note that this takes a single value in arg_z.  */
1392
1393_spentry(nthrow1value)
1394        __(movb $1,rcontext(tcr.unwinding))
1395local_label(_nthrow1v_nextframe):
1396        __(subl $fixnumone,%imm0)
1397        __(js local_label(_nthrow1v_done))
1398        __(movd %imm0,%mm0)
1399        __(movl rcontext(tcr.catch_top),%temp1)
1400        __(movl catch_frame.link(%temp1),%imm0)
1401        __(movl %imm0,rcontext(tcr.catch_top))
1402        __(movl catch_frame.db_link(%temp1),%imm0)
1403        __(cmpl %imm0,rcontext(tcr.db_link))
1404        __(jz local_label(_nthrow1v_dont_unbind))
1405        __(push %temp1)
1406        __(push %temp0)
1407        __(push %arg_z)
1408        __(push [$]local_label(_nthrow1v_back_from_unbind))
1409        __(jmp _SPunbind_to)
1410__(tra(local_label(_nthrow1v_back_from_unbind)))
1411        __(pop %arg_z)
1412        __(pop %temp0)
1413        __(pop %temp1)
1414local_label(_nthrow1v_dont_unbind):
1415        __(cmpb $unbound_marker,catch_frame.catch_tag(%temp1))
1416        __(je local_label(_nthrow1v_do_unwind))
1417/* A catch frame.  If the last one, restore context from there. */
1418        __(movd %mm0,%imm0)
1419        __(test %imm0,%imm0)    /* last catch frame? */
1420        __(jne local_label(_nthrow1v_skip))
1421        __(movl catch_frame.xframe(%temp1),%arg_y)
1422        __(movl %arg_y,rcontext(tcr.xframe))
1423        __(movl catch_frame.esp(%temp1),%esp)
1424        __(movl catch_frame.ebp(%temp1),%ebp)
1425        __(movd catch_frame.foreign_sp(%temp1),%stack_temp)
1426        __(movd %stack_temp,rcontext(tcr.foreign_sp))
1427local_label(_nthrow1v_skip):
1428        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
1429        __(movl %imm0,rcontext(tcr.save_tsp))
1430        __(movl %imm0,rcontext(tcr.next_tsp))
1431        __(movd %mm0,%imm0)
1432        __(jmp local_label(_nthrow1v_nextframe))
1433local_label(_nthrow1v_do_unwind):
1434/* This is harder, but not as hard (not as much BLTing) as the */
1435/* multiple-value case. */
1436        __(movl catch_frame.xframe(%temp1),%arg_y)
1437        __(movl %arg_y,rcontext(tcr.xframe))
1438        __(movl catch_frame.ebp(%temp1),%ebp)
1439        __(movl catch_frame.esp(%temp1),%esp)
1440        __(movd catch_frame.foreign_sp(%temp1),%stack_temp)
1441        __(movd %stack_temp,rcontext(tcr.foreign_sp))
1442        /* Discard the catch frame so we can build a temp frame. */
1443        __(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
1444        __(movl %imm0,rcontext(tcr.save_tsp))
1445        __(movl %imm0,rcontext(tcr.next_tsp))
1446        __(movl catch_frame.pc(%temp1),%xfn) /* xfn is temp1 */
1447        __(TSP_Alloc_Fixed((3*node_size),%imm0))
1448        __(addl $tsp_frame.fixed_overhead,%imm0)
1449        __(movl %ra0,(%imm0))
1450        __(movd %mm0,node_size*1(%imm0))
1451        __(movl %arg_z,node_size*2(%imm0))
1452/* Ready to call cleanup code.  Set up tra, jmp to %xfn. */
1453        __(push $local_label(_nthrow1v_called_cleanup))
1454        __(movb $0,rcontext(tcr.unwinding))
1455        __(jmp *%xfn)
1456__(tra(local_label(_nthrow1v_called_cleanup)))
1457        __(movb $1,rcontext(tcr.unwinding))
1458        __(movl rcontext(tcr.save_tsp),%imm0)
1459        __(movl tsp_frame.data_offset+(0*node_size)(%imm0),%ra0)
1460        __(movd tsp_frame.data_offset+(1*node_size)(%imm0),%mm0)
1461        __(movl tsp_frame.data_offset+(2*node_size)(%imm0),%arg_z)
1462        __(movl (%imm0),%imm0)
1463        __(movl %imm0,rcontext(tcr.save_tsp))
1464        __(movl %imm0,rcontext(tcr.next_tsp))
1465        __(movd %mm0,%imm0)
1466        __(jmp local_label(_nthrow1v_nextframe))
1467local_label(_nthrow1v_done):
1468        __(movb $0,rcontext(tcr.unwinding))
1469        __(check_pending_interrupt(%imm0))
1470local_label(_nthrow1v_return):
1471        __(jmp *%ra0)
1472_endsubp(nthrow1value)
1473
1474/* This never affects the symbol's vcell   */
1475/* Non-null symbol in arg_y, new value in arg_z           */
1476
1477_spentry(bind)
1478        __(movl symbol.binding_index(%arg_y),%imm0)
1479        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1480        __(jb 0f)
1481        __(push %imm0)
1482        __(tlb_too_small())
14830:      __(test %imm0,%imm0)
1484        __(jz 9f)
1485        __(movl rcontext(tcr.tlb_pointer),%temp1)
1486        __(push (%temp1,%imm0))
1487        __(push %imm0)
1488        __(push rcontext(tcr.db_link))
1489        __(movl %esp,rcontext(tcr.db_link))
1490        __(movl %arg_z,(%temp1,%imm0))
1491        __(jmp *%ra0)
14929:     
1493        __(movl %arg_y,%arg_z)
1494        __(movl $XSYMNOBIND,%arg_y)
1495        __(set_nargs(2))
1496        __(push %ra0)
1497        __(jmp _SPksignalerr)
1498_endsubp(bind)
1499
1500/* arg_z = symbol: bind it to its current value  */
1501
1502_spentry(bind_self)
1503        __(movl symbol.binding_index(%arg_z),%imm0)
1504        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1505        __(jb 0f)
1506        __(push %imm0)
1507        __(tlb_too_small())
15080:      __(test %imm0,%imm0)
1509        __(jz 9f)
1510        __(movl rcontext(tcr.tlb_pointer),%temp1)
1511        __(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
1512        __(jz 2f)
1513        __(push (%temp1,%imm0))
1514        __(push %imm0)
1515        __(push rcontext(tcr.db_link))
1516        __(movl %esp,rcontext(tcr.db_link))
1517        __(jmp *%ra0)
15182:      __(movl symbol.vcell(%arg_z),%arg_y)
1519        __(push (%temp1,%imm0))
1520        __(push %imm0)
1521        __(push rcontext(tcr.db_link))
1522        __(movl %arg_y,(%temp1,%imm0))
1523        __(movl %esp,rcontext(tcr.db_link))
1524        __(jmp *%ra0)
15259:      __(movl $XSYMNOBIND,%arg_y)
1526        __(set_nargs(2))
1527        __(push %ra0)
1528        __(jmp _SPksignalerr)
1529_endsubp(bind_self)
1530
1531_spentry(bind_nil)
1532        __(movl symbol.binding_index(%arg_z),%imm0)
1533        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1534        __(jb 0f)
1535        __(push %imm0)
1536        __(tlb_too_small())
15370:      __(test %imm0,%imm0)
1538        __(jz 9f)
1539        __(movl rcontext(tcr.tlb_pointer),%temp1)
1540        __(push (%temp1,%imm0))
1541        __(push %imm0)
1542        __(push rcontext(tcr.db_link))
1543        __(movl %esp,rcontext(tcr.db_link))
1544        __(movl $nil_value,(%temp1,%imm0))
1545        __(jmp *%ra0)
15469:      __(movl $XSYMNOBIND,%arg_y)
1547        __(set_nargs(2))
1548        __(push %ra0)
1549        __(jmp _SPksignalerr)
1550_endsubp(bind_nil)
1551
1552_spentry(bind_self_boundp_check)
1553        __(movl symbol.binding_index(%arg_z),%imm0)
1554        __(cmpl rcontext(tcr.tlb_limit),%imm0)
1555        __(jb 0f)
1556        __(push %imm0)
1557        __(tlb_too_small())
15580:      __(test %imm0,%imm0)
1559        __(jz 9f)
1560        __(movl rcontext(tcr.tlb_pointer),%temp1)
1561        __(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
1562        __(je 2f)
1563        __(cmpb $unbound_marker,(%temp1,%imm0))
1564        __(je 8f)
1565        __(push (%temp1,%imm0))
1566        __(push %imm0)
1567        __(push rcontext(tcr.db_link))
1568        __(movl %esp,rcontext(tcr.db_link))
1569        __(jmp *%ra0)
15702:      __(movl symbol.vcell(%arg_z),%arg_y)
1571        __(cmpl $unbound_marker,%arg_y)
1572        __(jz 8f)
1573        __(push (%temp1,%imm0))
1574        __(push %imm0)
1575        __(push rcontext(tcr.db_link))
1576        __(movl %esp,rcontext(tcr.db_link))
1577        __(movl %arg_y,(%temp1,%imm0))
1578        __(jmp *%ra0)
15798:      __(push %ra0)
1580        __(uuo_error_reg_unbound(Rarg_z))
1581       
15829:      __(movl $XSYMNOBIND,%arg_y)
1583        __(set_nargs(2))
1584        __(push %ra0)
1585        __(jmp _SPksignalerr)
1586_endsubp(bind_self_boundp_check)
1587
1588_spentry(conslist)
1589        __(movl %nargs,%imm0)
1590        __(movl %temp0,%temp1)  /* have to use temp0 for consing */
1591        __(movl $nil_value,%arg_z)
1592        __(test %imm0,%imm0)
1593        __(jmp 2f)
15941:      __(pop %arg_y)
1595        __(Cons(%arg_y,%arg_z,%arg_z))
1596        __(subl $node_size,%imm0)
15972:      __(jnz 1b)
1598        __(jmp *%temp1)
1599_endsubp(conslist)
1600
1601/* do list*: last arg in arg_z, all others pushed, nargs set to #args pushed.  */
1602/* Cons, one cons cell at at time.  Maybe optimize this later.  */
1603
1604_spentry(conslist_star)
1605        __(movl %nargs,%imm0)
1606        __(test %imm0,%imm0)
1607        __(movl %ra0,%temp1)
1608        __(jmp 2f)
16091:      __(pop %arg_y)
1610        __(Cons(%arg_y,%arg_z,%arg_z))
1611        __(subl $node_size,%imm0)
16122:      __(jnz 1b)
1613        __(jmp *%temp1)
1614_endsubp(conslist_star)
1615
1616/* We always have to create a tsp frame (even if nargs is 0), so the compiler */
1617/* doesn't get confused. */
1618_spentry(stkconslist)
1619        __(movl %ra0,rcontext(tcr.save0))
1620        __(movd %nargs,%mm0)
1621        __(movl %nargs,%temp0)
1622        __(addl %temp0,%temp0)
1623        __(movl $nil_value,%arg_z)
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        __(int $3)
1646        __(nop)
1647_endsubp(stkconslist_star)
1648
1649
1650/* Make a stack-consed simple-vector out of the NARGS objects   */
1651/*      on top of the vstack; return it in arg_z.  */
1652
1653_spentry(mkstackv)
1654        __(dnode_align(%nargs,tsp_frame.fixed_overhead+node_size,%imm0))
1655        __(TSP_Alloc_Var(%imm0,%arg_y))
1656        __(movl %nargs,%imm0)
1657        __(shll $(num_subtag_bits-fixnumshift),%imm0)
1658        __(movb $subtag_simple_vector,%imm0_b)
1659        __(movl %imm0,(%arg_y))
1660        __(leal fulltag_misc(%arg_y),%arg_z)
1661        __(test %nargs,%nargs)
1662        __(leal misc_data_offset(%arg_z,%nargs),%imm0)
1663        __(jmp 2f)
16641:      __(pop -node_size(%imm0))
1665        __(subl $node_size,%nargs)
1666        __(leal -node_size(%imm0),%imm0)
16672:      __(jne 1b)
1668        __(jmp *%ra0)   
1669_endsubp(mkstackv)
1670
1671        .globl C(egc_write_barrier_start)
1672C(egc_write_barrier_start):
1673/*  */
1674/* The function pc_luser_xp() - which is used to ensure that suspended threads  */
1675/* are suspended in a GC-safe way - has to treat these subprims (which implement  */
1676/* the EGC write-barrier) specially.  Specifically, a store that might introduce  */
1677/* an intergenerational reference (a young pointer stored in an old object) has  */
1678/* to "memoize" that reference by setting a bit in the global "refbits" bitmap.  */
1679/* This has to happen atomically, and has to happen atomically wrt GC.  */
1680
1681/* Note that updating a word in a bitmap is itself not atomic, unless we use  */
1682/* interlocked loads and stores.  */
1683
1684/* For RPLACA and RPLACD, things are fairly simple: regardless of where we are  */
1685/* in the function, we can do the store (even if it's already been done) and  */
1686/* calculate whether or not we need to set the bit out-of-line.  (Actually  */
1687/* setting the bit needs to be done atomically, unless we're sure that other  */
1688/* threads are suspended.)  */
1689/* We can unconditionally set the suspended thread's RIP to the return address.  */
1690
1691_spentry(rplaca)
1692        .globl C(egc_rplaca)
1693C(egc_rplaca):
1694        __(rcmpl(%arg_z,%arg_y))
1695        __(_rplaca(%arg_y,%arg_z))
1696        __(ja 1f)
16970:      __(repret)
16981:      __(movl %arg_y,%imm0)
1699        __(subl lisp_global(heap_start),%imm0)
1700        __(shrl $dnode_shift,%imm0)
1701        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1702        __(jae 0b)
1703        __(ref_global(refbits,%temp0))
1704        __(xorb $31,%imm0_b)
1705        __(lock)
1706        __(btsl %imm0,(%temp0))
1707        __(ret)
1708_endsubp(rplaca)
1709
1710_spentry(rplacd)
1711        .globl C(egc_rplacd)
1712C(egc_rplacd):
1713        __(rcmpl(%arg_z,%arg_y))
1714        __(_rplacd(%arg_y,%arg_z))
1715        __(ja 1f)
17160:      __(repret)
17171:      __(movl %arg_y,%imm0)
1718        __(subl lisp_global(heap_start),%imm0)
1719        __(shrl $dnode_shift,%imm0)
1720        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1721        __(jae 0b)
1722        __(ref_global(refbits,%temp0))
1723        __(xorb $31,%imm0_b)
1724        __(lock)
1725        __(btsl %imm0,(%temp0))
1726        __(ret)
1727_endsubp(rplacd)
1728
1729/* Storing into a gvector can be handles the same way as storing into a CONS. */
1730/* args (src, unscaled-idx, val) in temp0, arg_y, arg_z */
1731_spentry(gvset)
1732        .globl C(egc_gvset)
1733C(egc_gvset):
1734        __(movl %arg_z,misc_data_offset(%temp0,%arg_y))
1735        __(rcmpl(%arg_z,%temp0))
1736        __(ja 1f)
17370:      __(repret)
17381:      __(lea misc_data_offset(%temp0,%arg_y),%imm0)
1739        __(subl lisp_global(heap_start),%imm0)
1740        __(shrl $dnode_shift,%imm0)
1741        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1742        __(jae 0b)
1743        __(ref_global(refbits,%temp0))
1744        __(xorb $31,%imm0_b)
1745        __(lock)
1746        __(btsl %imm0,(%temp0))
1747        __(ret)
1748_endsubp(gvset)
1749
1750/* This is a special case of storing into a gvector: if we need to  */
1751/* memoize the store, record the address of the hash-table vector  */
1752/* in the refmap, as well.  */
1753
1754_spentry(set_hash_key)
1755        .globl C(egc_set_hash_key)
1756C(egc_set_hash_key):
1757        __(movl %arg_z,misc_data_offset(%temp0,%arg_y))
1758        __(rcmpl(%arg_z,%temp0))
1759        __(ja 1f)
17600:      __(repret)
17611:      __(lea misc_data_offset(%temp0,%arg_y),%imm0)
1762        __(subl lisp_global(heap_start),%imm0)
1763        __(shrl $dnode_shift,%imm0)
1764        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1765        __(jae 0b)
1766        __(ref_global(refbits,%temp1))
1767        __(xorb $31,%imm0_b)
1768        __(lock)
1769        __(btsl %imm0,(%temp1))
1770        /* Now memoize the address of the hash vector */
1771        __(movl %temp0,%imm0)
1772        __(subl lisp_global(heap_start),%imm0)
1773        __(shrl $dnode_shift,%imm0)
1774        __(xorb $31,%imm0_b)
1775        __(lock)
1776        __(btsl %imm0,(%temp1))
1777        __(ret)
1778_endsubp(set_hash_key)
1779
1780/* This is a little trickier: if this is interrupted, we need to know  */
1781/* whether or not the STORE-CONDITIONAL (cmpxchgq) has won or not.    */
1782/* If we're interrupted   before the PC has reached the "success_test" label, */
1783/* repeat (luser the PC back to .SPstore_node_conditional.)  If we're at that */
1784/* label with the Z flag set, we won and (may) need to memoize.  */
1785
1786/* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
1787_spentry(store_node_conditional)
1788        .globl C(egc_store_node_conditional)
1789C(egc_store_node_conditional):
1790        __(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
1791        __(sarl $fixnumshift,%temp0)    /* will be fixnum-tagged */
17920:      __(cmpl %arg_y,misc_data_offset(%temp1,%temp0))
1793        __(movl misc_data_offset(%temp1,%temp0),%imm0)
1794        __(jne 3f)
1795        __(lock)
1796        __(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
1797        .globl C(egc_store_node_conditional_success_test)
1798C(egc_store_node_conditional_success_test):
1799        __(jne 0b)
1800        __(leal misc_data_offset(%temp1,%temp0),%imm0)
1801        __(subl lisp_global(heap_start),%imm0)
1802        __(shrl $dnode_shift,%imm0)
1803        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1804        __(jae 2f)
1805        __(ref_global(refbits,%temp1))
1806        __(xorb $31,%imm0_b)
1807        __(lock)
1808        __(btsl %imm0,(%temp1))
1809        .globl C(egc_store_node_conditional_success_end)
1810C(egc_store_node_conditional_success_end):
18112:      __(movl $t_value,%arg_z)
1812        __(ret)
18133:      __(movl $nil_value,%arg_z)
1814        __(ret)
1815_endsubp(store_node_conditional)
1816
1817        /* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
1818_spentry(set_hash_key_conditional)
1819        .globl C(egc_set_hash_key_conditional)
1820C(egc_set_hash_key_conditional):
1821        __(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
1822        __(sarl $fixnumshift,%temp0)    /* will be fixnum-tagged */
18230:      __(cmpl %arg_y,misc_data_offset(%temp1,%temp0))
1824        __(movl misc_data_offset(%temp1,%temp0),%imm0)
1825        __(jne 3f)
1826        __(lock)
1827        __(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
1828        .globl C(egc_set_hash_key_conditional_success_test)
1829C(egc_set_hash_key_conditional_success_test):
1830        __(jne 0b)
1831        __(leal misc_data_offset(%temp1,%temp0),%imm0)
1832        __(subl lisp_global(heap_start),%imm0)
1833        __(shrl $dnode_shift,%imm0)
1834        __(cmpl lisp_global(oldspace_dnode_count),%imm0)
1835        __(jae 2f)
1836        __(ref_global(refbits,%temp0))
1837        __(xorb $31,%imm0_b)
1838        __(lock)
1839        __(btsl %imm0,(%temp0))
1840        /* Now memoize the address of the hash vector */
1841        __(movl %temp1,%imm0)
1842        __(subl lisp_global(heap_start),%imm0)
1843        __(shrl $dnode_shift,%imm0)
1844        __(xorb $31,%imm0_b)
1845        __(lock)
1846        __(btsl %imm0,(%temp0))
1847        .globl C(egc_write_barrier_end)
1848C(egc_write_barrier_end):
18492:      __(movl $t_value,%arg_z)
1850        __(ret)
18513:      __(movl $nil_value,%arg_z)
1852        __(ret)
1853_endsubp(store_node_conditional)
1854
1855_spentry(setqsym)
1856        __(bt $sym_vbit_const,symbol.flags(%arg_y))
1857        __(jae _SPspecset)
1858        __(mov %arg_y,%arg_z)
1859        __(mov $XCONST,%arg_y)
1860        __(set_nargs(2))
1861        __(jmp _SPksignalerr)
1862_endsubp(setqsym)
1863
1864_spentry(progvsave)
1865        __(push %arg_y)
1866       
1867        /* Error if arg_z isn't a proper list.  That's unlikely,  */
1868        /* but it's better to check now than to crash later.  */
1869       
1870        __(compare_reg_to_nil(%arg_z))
1871        __(movl %arg_z,%temp0)  /* fast   */
1872        __(movl %arg_z,%temp1)  /* slow   */
1873        __(je 9f)               /* Null list is proper   */
18740:
1875        __(extract_lisptag(%temp0,%imm0))
1876        __(cmpb $tag_list,%imm0_b)
1877        __(jne 8f)
1878        __(compare_reg_to_nil(%temp0))
1879        __(je 9f)
1880        __(_cdr(%temp0,%arg_y)) /* (null (cdr fast)) ?   */
1881        __(compare_reg_to_nil(%arg_y))
1882        __(je 9f)
1883        __(extract_lisptag(%arg_y,%imm0))
1884        __(cmpb $tag_list,%imm0_b)
1885        __(jne 8f)
1886        __(_cdr(%arg_y,%temp0))
1887        __(_cdr(%temp1,%temp1))
1888        __(cmpl %temp1,%temp0)
1889        __(jne 0b)
1890
18918:      __(add $node_size,%esp) /* discard pushed arg_y */
1892        __(movl $XIMPROPERLIST,%arg_y)
1893        __(set_nargs(2))
1894        __(jmp _SPksignalerr)
18959:      /* Whew           */
1896
1897        /* Next, determine the length of arg_y.  We   */
1898        /* know that it's a proper list.   */
1899        __(pop %arg_y)
1900       
1901        __(movl $-fixnumone,%imm0)
1902        __(movl %arg_y,%temp0)
19031:      __(compare_reg_to_nil(%temp0))
1904        __(_cdr(%temp0,%temp0))
1905        __(leal fixnumone(%imm0),%imm0)
1906        __(jne 1b)
1907       
1908        /* imm0 is now (boxed) triplet count.  */
1909        /* Determine word count, add 1 (to align), and make room.  */
1910        /*  if count is 0, make an empty tsp frame and exit   */
1911        __(testl %imm0,%imm0)
1912        __(jne 2f)
1913        __(TSP_Alloc_Fixed(2*node_size,%imm0))
1914        __(ret)
19152:      __(movl %imm0,%temp1)
1916        __(add %imm0,%imm0)
1917        __(add %temp1,%imm0)
1918        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
1919        __(TSP_Alloc_Var(%imm0,%temp0))
1920        __(movl %temp1,(%temp0))
1921        __(movd rcontext(tcr.db_link),%mm0)
19223:      __(movl $unbound_marker,%temp0)
1923        __(compare_reg_to_nil(%arg_z))
1924        __(cmovnel cons.car(%arg_z),%temp0)
1925        __(cmovnel cons.cdr(%arg_z),%arg_z)
1926        __(_car(%arg_y,%temp1))
1927        __(_cdr(%arg_y,%arg_y))
1928        __(movl symbol.binding_index(%temp1),%temp1)
1929        __(cmp rcontext(tcr.tlb_limit),%temp1)
1930        __(jb 4f)
1931        __(push %temp1)
1932        __(tlb_too_small())
19334:      __(push %arg_z)
1934        __(movl rcontext(tcr.tlb_pointer),%arg_z)
1935        __(subl $binding.size,%imm0)
1936        __(movl %temp1,binding.sym(%imm0))
1937        __(push (%arg_z,%temp1))
1938        __(pop binding.val(%imm0))
1939        __(movl %temp0,(%arg_z,%temp1))
1940        __(pop %arg_z)
1941        __(movd %mm0,binding.link(%imm0))
1942        __(movd %imm0,%mm0)
1943        __(compare_reg_to_nil(%arg_y))
1944        __(jne 3b)
1945        __(movd %mm0,rcontext(tcr.db_link))
1946        __(ret)
1947_endsubp(progvsave)
1948
1949/* Allocate node objects on the temp stack, immediate objects on the foreign  */
1950/* stack. (The caller has to know which stack to discard a frame from.)  */
1951/* %arg_y = boxed element-count, %arg_z = boxed subtype  */
1952
1953_spentry(stack_misc_alloc)
1954        __(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
1955        __(jne local_label(stack_misc_alloc_not_u24))
1956        __(unbox_fixnum(%arg_z,%imm0))
1957        __(mov %arg_y,%temp0)
1958        __(shl $num_subtag_bits-fixnumshift,%temp0)
1959        __(or %temp0,%imm0)     /* %imm0 now = header */
1960        __(movd %imm0,%mm0)     /* cache header in %mm0 */
1961        __(andb $fulltagmask,%imm0_b)
1962        __(cmpb $fulltag_nodeheader,%imm0_b)
1963        __(je local_label(stack_misc_alloc_node))
1964        __(movd %mm0,%imm0)
1965        __(cmpb $max_32_bit_ivector_subtag,%imm0_b)
1966        __(jbe local_label(stack_misc_alloc_32))
1967        __(cmpb $max_8_bit_ivector_subtag,%imm0_b)
1968        __(jbe local_label(stack_misc_alloc_8))
1969        __(cmpb $max_16_bit_ivector_subtag,%imm0_b)
1970        __(jbe local_label(stack_misc_alloc_16))
1971        __(cmpb $subtag_double_float_vector,%imm0_b)
1972        __(jne local_label(stack_misc_alloc_1))
1973        /* double-float vector case */
1974        __(imul $2,%arg_y,%imm0)
1975        __(jmp local_label(stack_misc_alloc_alloc_ivector))
1976local_label(stack_misc_alloc_1):
1977        __(unbox_fixnum(%arg_y,%imm0))
1978        __(addl $7,%imm0)
1979        __(shrl $3,%imm0)
1980        __(jmp local_label(stack_misc_alloc_alloc_ivector))
1981local_label(stack_misc_alloc_8):
1982        __(unbox_fixnum(%arg_y,%imm0))
1983        __(jmp local_label(stack_misc_alloc_alloc_ivector))
1984local_label(stack_misc_alloc_16):
1985        __(unbox_fixnum(%arg_y,%imm0))
1986        __(shl $1,%imm0)
1987        __(jmp local_label(stack_misc_alloc_alloc_ivector))
1988local_label(stack_misc_alloc_32):
1989        __(mov %arg_y,%imm0)
1990local_label(stack_misc_alloc_alloc_ivector):
1991        /* byte count in %imm0 */
1992        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
1993        __(cmpl $tstack_alloc_limit,%imm0)
1994        __(ja local_label(stack_misc_alloc_heap_alloc_ivector))
1995        __(movd rcontext(tcr.foreign_sp),%stack_temp)
1996        __(movd %stack_temp,%temp1)
1997        __(subl %imm0,rcontext(tcr.foreign_sp))
1998        __(movl rcontext(tcr.foreign_sp),%temp0)
19990:      __(movsd %fpzero,-dnode_size(%temp1))
2000        __(subl $dnode_size,%temp1)
2001        __(cmpl %temp1,%temp0)
2002        __(jnz 0b)
2003        __(movd %stack_temp,(%temp0))
2004        __(movl %ebp,csp_frame.save_ebp(%temp0))
2005        __(movd %mm0,csp_frame.fixed_overhead(%temp0))
2006        __(lea csp_frame.fixed_overhead+fulltag_misc(%temp0),%arg_z)
2007        __(ret)
2008local_label(stack_misc_alloc_heap_alloc_ivector):
2009        __(movd rcontext(tcr.foreign_sp),%stack_temp)
2010        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2011        __(movl rcontext(tcr.foreign_sp),%imm0)
2012        __(movd %stack_temp,(%imm0))
2013        __(jmp _SPmisc_alloc)
2014local_label(stack_misc_alloc_node):
2015        __(movl %arg_y,%imm0)
2016        __(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
2017        __(cmpl $tstack_alloc_limit,%imm0)
2018        __(ja local_label(stack_misc_alloc_heap_alloc_gvector))
2019        __(TSP_Alloc_Var(%imm0,%temp1))
2020        __(movd %mm0,(%temp1))
2021        __(leal fulltag_misc(%temp1),%arg_z)
2022        __(ret)
2023local_label(stack_misc_alloc_heap_alloc_gvector):
2024        __(TSP_Alloc_Fixed(0,%imm0))
2025        __(jmp _SPmisc_alloc)
2026
2027local_label(stack_misc_alloc_not_u24):
2028        __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_24))
2029_endsubp(stack_misc_alloc)
2030
2031/* subtype (boxed, of course) is pushed, followed by nargs bytes worth of */
2032/* initial-contents.  Note that this can be used to cons any type of */
2033/* initialized node-header'ed misc object (symbols, closures, ...) */
2034/* as well as vector-like objects. */
2035_spentry(gvector)
2036        __(subl $node_size,%nargs)      /* off by one in x862-%gvector */
2037        __(movl (%esp,%nargs),%imm0)    /* boxed subtype */
2038        __(sarl $fixnumshift,%imm0)
2039        __(movl %nargs,%arg_z)
2040        __(shll $num_subtag_bits-word_shift,%arg_z)
2041        __(orl %arg_z,%imm0)
2042        __(movd %imm0,%mm0)
2043        __(dnode_align(%nargs,node_size,%imm0))
2044        __(push %ra0)   /* aka %temp0, can't be live while consing */
2045        __(Misc_Alloc(%arg_z))
2046        __(pop %ra0)
2047        __(movl %nargs,%imm0)
2048        __(jmp 2f)
20491:      __(movl %arg_y,misc_data_offset(%arg_z,%imm0))
20502:      __(subl $node_size,%imm0)
2051        __(pop %arg_y)  /* Note the intentional fencepost: */
2052                        /* discard the subtype as well. */
2053        __(jge 1b)
2054        __(jmp *%ra0)
2055_endsubp(gvector)
2056
2057_spentry(mvpass)
2058        __(int $3)
2059_endsubp(mvpass)
2060
2061_spentry(nthvalue)
2062        __(int $3)
2063_endsubp(nthvalue)
2064
2065_spentry(values)
2066        __(movl (%temp0),%arg_y)        /* return address */
2067        __(ref_global(ret1val_addr,%imm0))
2068        __(movl $nil_value,%arg_z)
2069        __(cmpl %imm0,%arg_y)
2070        __(je 0f)
2071        __(test %nargs,%nargs)
2072        __(cmovne -node_size(%esp,%nargs),%arg_z)
2073        __(movl %temp0,%esp)
2074        __(ret)
20750:      __(movl 4(%temp0),%arg_y)
2076        __(addl $2*node_size,%temp0)
2077        __(lea (%esp,%nargs),%imm0)
2078        __(movd %nargs,%mm0)
2079        __(jmp 2f)
20801:      __(subl $node_size,%imm0)
2081        __(movl (%imm0),%temp1)
2082        __(subl $node_size,%temp0)
2083        __(movl %temp1,(%temp0))
20842:      __(cmp %imm0,%esp)
2085        __(jne 1b)
2086        __(movl %temp0,%esp)
2087        __(movd %mm0,%nargs)
2088        __(jmp *%arg_y)
2089
2090_endsubp(values)
2091
2092_spentry(default_optional_args)
2093        __(int $3)
2094_endsubp(default_optional_args)
2095
2096_spentry(opt_supplied_p)
2097        __(int $3)
2098_endsubp(opt_supplied_p)
2099
2100_spentry(lexpr_entry)
2101        __(int $3)
2102_endsubp(lexpr_entry)
2103
2104_spentry(heap_rest_arg)
2105        __(push_argregs())
2106        __(movl %temp0,%arg_y)
2107        __(movl %nargs,%imm0)
2108        __(testl %imm0,%imm0)
2109        __(movl $nil_value,%arg_z)
2110        __(jmp 2f)
2111        .p2align 4
21121:      __(pop %temp1)
2113        __(Cons(%temp1,%arg_z,%arg_z))
2114        __(subl $node_size,%imm0)
21152:      __(jg 1b)
2116        __(push %arg_z)
2117        __(movl %arg_y,%temp0)
2118        __(jmp *%ra0)
2119
2120_endsubp(heap_rest_arg)
2121
2122/* %imm0 contains the number of fixed args; make an &rest arg out of */
2123/* the others. */
2124_spentry(req_heap_rest_arg)
2125        __(push_argregs())
2126        __(movd %nargs,%mm0)
2127        __(subl %imm0,%nargs)
2128        __(movl %nargs,%imm0)
2129        __(movl %temp0,%temp1)
2130        __(movl $nil_value,%arg_z)
2131        __(jmp 2f)
2132        .p2align 4
21331:      __(pop %arg_y)
2134        __(Cons(%arg_y,%arg_z,%arg_z))
2135        __(subl $node_size,%imm0)
21362:      __(jg 1b)
2137        __(push %arg_z)
2138        __(movl %temp1,%temp0)
2139        __(movd %mm0,%nargs)
2140        __(jmp *%ra0)
2141_endsubp(req_heap_rest_arg)
2142
2143/* %imm0 bytes of stuff has already been pushed   */
2144/* make an &rest arg out of any others   */
2145_spentry(heap_cons_rest_arg)
2146        __(movd %nargs,%mm0)
2147        __(subl %imm0,%nargs)
2148        __(movl %nargs,%imm0)
2149        __(movl $nil_value,%arg_z)
2150        __(movl %ra0,%arg_y)    /* temp0 can't be live while consing */
2151        __(jmp 2f)              /* (did I mention that already?) */
2152        .p2align 4
21531:      __(pop %temp1)
2154        __(Cons(%temp1,%arg_z,%arg_z))
2155        __(subl $node_size,%imm0)
21562:      __(jg 1b)
2157        __(push %arg_z)
2158        __(movd %mm0,%nargs)
2159        __(jmp *%arg_y)
2160_endsubp(heap_cons_rest_arg)
2161
2162_spentry(simple_keywords)
2163        __(xor %imm0,%imm0)
2164        __(push_argregs())
2165        __(jmp _SPkeyword_bind)
2166_endsubp(simple_keywords)
2167
2168_spentry(keyword_args)
2169        __(push_argregs())
2170        __(jmp _SPkeyword_bind)
2171_endsubp(keyword_args)
2172
2173/* There are %nargs words of arguments on the stack; %imm0 contains the */
2174/* number of non-keyword args pushed.  It's possible that we never actually */
2175/* got any keyword args, which would make things much simpler. */
2176
2177/* On entry, the upper half of %temp1 (aka %nargs) contains some bits */
2178/* indicating whether &allow-other-keys and/or &rest was present in the */
2179/* lambda list. */
2180
2181/* Once we get here, we can use the arg registers. */
2182
2183/* N.B.: %ra0 is %temp0, and must not be clobbered. */
2184
2185define([keyword_flags_aok_bit],[16])
2186define([keyword_flags_unknown_keys_bit],[17])
2187define([keyword_flags_rest_bit],[18])
2188define([keyword_flags_seen_aok_bit],[19])
2189
2190_spentry(keyword_bind)
2191        __(movl %temp1,rcontext(tcr.unboxed0))  /* save keyword flags */
2192        __(movzwl %nargs_w,%nargs)
2193        __(movl %nargs,%arg_z)
2194        __(subl %imm0,%arg_z)
2195        __(jbe local_label(no_keyword_values))
2196        __(btl $word_shift,%arg_z)
2197        __(jnc local_label(even))
2198        __(movl $nil_value,%arg_y)
2199        __(movl %arg_z,%nargs)
2200        __(test %nargs,%nargs)
2201        __(movl %ra0,rcontext(tcr.save0))       /* save temp0 while consing */
2202        __(jmp 1f)
22030:      __(pop %arg_z)
2204        __(Cons(%arg_z,%arg_y,%arg_y))
2205        __(subl $node_size,%nargs)
22061:      __(jnz 0b)
2207        __(movl rcontext(tcr.save0),%ra0)
2208        __(movapd %fpzero,rcontext(tcr.save0))
2209        __(movl %arg_y,%arg_z)
2210        __(movl $XBADKEYS,%arg_y)
2211        __(set_nargs(2))
2212        __(jmp _SPksignalerr)
2213
2214        /* Now that we're sure that we have an even number of */
2215        /* keywords and values (in %arg_z), move the pairs over */
2216        /* to the temp stack. */
2217local_label(even):
2218        __(lea tsp_frame.fixed_overhead(%arg_z),%arg_y)
2219        __(TSP_Alloc_Var(%arg_y,%imm0))
22202:      __(subl $node_size,%arg_y)
2221        __(pop (%arg_y))
2222        __(cmpl %arg_y,%imm0)
2223        __(jne 2b)
2224
2225        /* Get the keyword vector into %arg_y, and its length into %imm0. */
2226        /* Push %imm0 pairs of NILs (representing value, supplied-p) */
2227        /* for each declared keyword. */
2228        __(movzwl misc_data_offset(%fn),%imm0)
2229        __(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
2230        __(vector_length(%arg_y,%imm0))
2231        __(jmp 4f)
22323:      __(push $nil_value)
2233        __(push $nil_value)
22344:      __(subl $fixnumone,%imm0)
2235        __(jge 3b)
2236
2237        /* We can now push %ra0 (aka %temp0) and %nargs (aka %temp1) */
2238        /* in order to get a couple more registers to work with. */
2239        __(push %ra0)
2240        __(push %nargs)
2241
2242        /* At this point we have: */
2243        /* number of supplied keywords and values in %arg_z */
2244        /* keyword vector in %arg_y */
2245        __(vector_length(%arg_y,%imm0))
2246        __(push %imm0)          /* count of declared keywords */
2247        __(push %arg_z)         /* count of supplied keys and values */
2248
2249        /* For each declared keyword, iterate over the supplied k/v pairs */
2250        /* to see if it's supplied and what the value is. */
2251        /* checking to see if any */
2252        /* key-value pairs were unexpectedly supplied. */
2253
2254        __(movl rcontext(tcr.save_tsp),%temp0)
2255        __(addl $2*node_size,%temp0) /* skip frame overhead */
2256        /* %temp0: top of tstack (skipping frame overhead) */
2257        __(lea 4*node_size(%esp,%imm0,2),%temp1)
2258        /* %temp1: word above 0th value/supplied-p pair on vstack */
2259        /* %arg_y: keyword vector */
2260        __(xorl %imm0,%imm0)
2261        /* %imm0: index */
2262        /* %arg_z: temporary */
2263
2264        /* Iterate over supplied k/v pairs on tstack.  See if key is */
2265        /* in the keyword vector.  Copy value and set supplied-p on */
2266        /* vstack if found. */
2267
2268local_label(tstack_loop):
2269        __(movl (%temp0,%imm0,2),%arg_z)        /* keyword */
2270        __(push %imm0)
2271        __(xorl %imm0,%imm0)
2272        __(cmpl $nrs.kallowotherkeys,%arg_z)
2273        __(jne local_label(next_keyvect_entry))
2274        __(btsl $keyword_flags_seen_aok_bit,rcontext(tcr.unboxed0))
2275        __(jc local_label(next_keyvect_entry))
2276        __(push %imm0)
2277        __(movl 4(%esp),%imm0)
2278        __(cmpl $nil_value,node_size(%temp0,%imm0,2))
2279        __(pop %imm0)
2280        __(je local_label(next_keyvect_entry))
2281        __(btsl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2282        __(jmp local_label(next_keyvect_entry))
2283        /* loop through keyword vector */
22846:      __(cmpl misc_data_offset(%arg_y,%imm0),%arg_z)
2285        __(jne 7f)
2286        /* Got a match; have we already seen this keyword? */
2287        __(negl %imm0)
2288        __(cmpl $nil_value,-node_size*2(%temp1,%imm0,2))
2289        __(jne 9f)      /* seen it, ignore this value */
2290        __(movl (%esp),%arg_z)
2291        __(lea (%temp0,%arg_z,2),%arg_z)
2292        __(movl node_size(%arg_z),%arg_z) /* value for this key */
2293        __(movl %arg_z,-node_size(%temp1,%imm0,2))
2294        __(movl $t_value,-node_size*2(%temp1,%imm0,2))
2295        __(jmp 9f)
22967:      __(addl $node_size,%imm0)
2297local_label(next_keyvect_entry):
2298        __(cmpl %imm0,8(%esp))
2299        __(jne 6b)
2300        /* Didn't match anything in the keyword vector.  Is the keyword */
2301        /* :allow-other-keys? */
2302        __(cmpl $nrs.kallowotherkeys,%arg_z)
2303        __(je 9f)       /* :allow-other-keys is never "unknown" */
23048:      __(btsl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
23059:      __(pop %imm0)
2306        __(addl $fixnumone,%imm0)
2307        __(movl %imm0,%arg_z)
2308        __(shll $1,%arg_z)      /* pairs of tstack words */
2309        __(cmpl %arg_z,0(%esp))
2310        __(jne local_label(tstack_loop))
2311
2312        __(pop %imm0)   /* count of supplied keys and values */
2313        __(addl $node_size,%esp)
2314        __(pop %nargs)
2315        __(pop %ra0)
2316
2317        /* If the function takes an &rest arg, or if we got an unrecognized */
2318        /* keyword and don't allow that, copy the incoming k/v pairs from */
2319        /* the temp stack back to the value stack. */
2320        __(btl $keyword_flags_rest_bit,rcontext(tcr.unboxed0))
2321        __(jc 1f)
2322        __(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
2323        __(jnc 0f)
2324        __(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2325        __(jnc 1f)
2326        /* pop the tstack frame */
23270:      __(discard_temp_frame(%imm0))
2328        __(jmp *%ra0)
2329
2330        /* Copy the k/v pairs from the tstack back to the value stack, */
2331        /* either because the function takes an &rest arg or because */
2332        /* we need to signal an "unknown keywords" error. */
23331:      __(movl rcontext(tcr.save_tsp),%arg_z)
2334        __(mov (%arg_z),%arg_y)
2335        __(jmp 3f)
23362:      __(push (%arg_z))
2337        __(push node_size(%arg_z))
23383:      __(addl $dnode_size,%arg_z)
2339        __(cmpl %arg_z,%arg_y)
2340        __(jne 2b)
2341        __(discard_temp_frame(%arg_z))
2342        __(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
2343        __(jnc 9f)
2344        __(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
2345        __(jc 9f)
2346        /* Signal an "unknown keywords" error */
2347        __(movl %imm0,%nargs)
2348        __(movl $nil_value,%arg_z)
2349        __(test %nargs,%nargs)
2350        __(movl %ra0,rcontext(tcr.save0))
2351        __(jmp 5f)
23524:      __(pop %arg_y)
2353        __(Cons(%arg_y,%arg_z,%arg_z))
2354        __(subl $node_size,%nargs)
23555:      __(jnz 4b)
2356        __(movl $XBADKEYS,%arg_y)
2357        __(set_nargs(2))
2358        __(movl rcontext(tcr.save0),%ra0)
2359        __(movl $0,rcontext(tcr.save0))
2360        __(jmp _SPksignalerr)
23619:      __(jmp *%ra0)
2362
2363/* No keyword value were provided.  Access the keyword vector (which is the */
2364/* 0th constant in %fn), determine its length N, and push N pairs of NILs. */
2365/* N could be 0... */
2366
2367local_label(no_keyword_values):
2368        __(movzwl misc_data_offset(%fn),%imm0)
2369        __(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
2370        __(vector_length(%arg_y,%arg_z))
2371        __(movl $nil_value,%imm0)
2372        __(jmp 1f)
23730:      __(push %imm0)
2374        __(push %imm0)
23751:      __(subl $fixnumone,%arg_z)
2376        __(jge 0b)
2377        __(jmp *%ra0)
2378_endsubp(keyword_bind)
2379
2380/* Normally, we'd just set %fname (aka %temp0) and do */
2381/* jump_fname().  Sometimes, though, %temp0 is being used */
2382/* as %ra0, and I'm not sure that it's going to be safe to */
2383/* clobber that.  (Note that nil-relative symbols aren't going */
2384/* get moved around by the GC, so we can get away with putting */
2385/* '%err-disp in %imm0.) */
2386_spentry(ksignalerr)
2387        __(mov $nrs.errdisp,%imm0)
2388        __(mov symbol.fcell(%imm0),%fn)
2389        __(jump_fn)
2390_endsubp(ksignalerr)
2391
2392_spentry(stack_rest_arg)
2393        __(xorl %imm0,%imm0)
2394        __(push_argregs())
2395        __(jmp _SPstack_cons_rest_arg)
2396_endsubp(stack_rest_arg)
2397
2398_spentry(req_stack_rest_arg)
2399        __(push_argregs())
2400        __(jmp _SPstack_cons_rest_arg)
2401_endsubp(req_stack_rest_arg)
2402
2403_spentry(stack_cons_rest_arg)
2404        __(movd %nargs,%mm2)
2405        __(movl %temp0,rcontext(tcr.save0))
2406        __(subl %imm0,%temp1)
2407        __(movl $nil_value,%arg_z)
2408        __(jle 2f)      /* empty list; make an empty TSP frame */
2409        __(addl %temp1,%temp1)
2410        __(cmpl $(tstack_alloc_limit-dnode_size),%temp1)
2411        __(ja 3f)       /* make empty frame, then heap-cons */
2412        __(dnode_align(%temp1,tsp_frame.fixed_overhead,%imm0))
2413        __(TSP_Alloc_Var(%imm0,%temp0))
2414        __(addl $fulltag_cons,%temp0)
24151:      __(pop %arg_y)
2416        __(_rplacd(%temp0,%arg_z))
2417        __(_rplaca(%temp0,%arg_y))
2418        __(movl %temp0,%arg_z)
2419        __(addl $cons.size,%temp0)
2420        __(subl $dnode_size,%temp1)
2421        __(jne 1b)
2422        __(push %arg_z)
2423        __(movd %mm2,%nargs)
2424        __(movl rcontext(tcr.save0),%temp0)
2425        __(movss %fpzero,rcontext(tcr.save0))
2426        __(jmp *%temp0)
2427/* Length 0, make empty frame */
24282:
2429        __(TSP_Alloc_Fixed(0,%temp0))
2430        __(push %arg_z)
2431        __(movd %mm2,%nargs)
2432        __(movl rcontext(tcr.save0),%temp0)
2433        __(movss %fpzero,rcontext(tcr.save0))
2434        __(jmp *%temp0)
2435/* Too big to stack-cons, but make an empty frame before heap-consing */
2436        __(TSP_Alloc_Fixed(0,%temp0))
2437        __(movd %mm2,%nargs)
2438        __(movl rcontext(tcr.save0),%temp0)
2439        __(movss %fpzero,rcontext(tcr.save0))
2440        __(jmp _SPheap_cons_rest_arg)
2441_endsubp(stack_cons_rest_arg)
2442
2443_spentry(getxlong)
2444        __(int $3)
2445_endsubp(getxlong)
2446
2447/* Have to be a little careful here: the caller may or may not have pushed  */
2448/* an empty frame, and we may or may not have needed one.  We can't easily  */
2449/* tell whether or not a frame will be needed (if the caller didn't reserve  */
2450/* a frame, whether or not we need one depends on the length of the list  */
2451/* in arg_z.  So, if the caller didn't push a frame, we do so; once */
2452/* everything's been spread, we discard the reserved frame (regardless of
2453/* who pushed it) if all args fit in registers.   */
2454
2455/* xxx preserve temp1 somehow? cf. comment in x862-invoke-fn */
2456_spentry(spreadargz)
2457        __(test %nargs,%nargs)
2458        __(jne 0f)
2459        __(push $reserved_frame_marker)
2460        __(push $reserved_frame_marker)
24610:      __(movl %arg_z,rcontext(tcr.save0))     /* save in case of error */
2462        __(movd %nargs,%mm0)    /* now we can use %temp1 */
2463        __(xorl %nargs,%nargs)
2464        __(cmpl $nil_value,%arg_z)
2465        __(je 2f)
24661:      __(extract_fulltag(%arg_z,%imm0))
2467        __(cmpb $fulltag_cons,%imm0_b)
2468        __(jne 9f)
2469        __(_car(%arg_z,%arg_y))
2470        __(_cdr(%arg_z,%arg_z))
2471        __(add $node_size,%nargs)
2472        __(cmpl $call_arguments_limit<<fixnumshift,%nargs)
2473        __(jge 8f)
2474        __(push %arg_y)
2475        __(cmpl $nil_value,%arg_z)
2476        __(jne 1b)
24772:      __(movd %mm0,%imm0)
2478        __(addl %imm0,%nargs)
2479        __(jne 4f)
24803:      __(addl $2*node_size,%esp)
2481        __(movl $0,rcontext(tcr.save0))
2482        __(jmp *%ra0)
24834:      __(pop %arg_z)
2484        __(cmp $1*node_size,%nargs)
2485        __(je 3b)
2486        __(pop %arg_y)
2487        __(cmp $2*node_size,%nargs)
2488        __(je 3b)
2489        __(movl $0,rcontext(tcr.save0))
2490        __(jmp *%ra0)
2491/* Discard everything that's been pushed already, complain */
24928:      __(lea (%esp,%nargs),%esp)
2493        __(movl rcontext(tcr.save0),%arg_z) /* recover original */
2494        __(movl $0,rcontext(tcr.save0))
2495        __(movl $XTMINPS,%arg_y)
2496        __(set_nargs(2))
2497        __(push %ra0)
2498        __(jmp _SPksignalerr)
24999:      __(lea (%esp,%nargs),%esp)
2500        __(movl rcontext(tcr.save0),%arg_z) /* recover original */
2501        __(movl $0,rcontext(tcr.save0))
2502        __(movl $XNOSPREAD,%arg_y)
2503        __(set_nargs(2))
2504        __(push %ra0)
2505        __(jmp _SPksignalerr)
2506_endsubp(spreadargz)
2507
2508
2509/* Caller built its own frame when it was entered.  If all outgoing args  */
2510/* are in registers, we can discard that frame; otherwise, we copy outgoing  */
2511/* relative to it and restore %rbp/%ra0   */
2512_spentry(tfuncallgen)
2513        __(cmpl $nargregs*node_size,%nargs)
2514        __(jbe 9f)
2515        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2516        __(movl %temp0,rcontext(tcr.save0))
2517        __(movd %nargs,%mm0)
2518        __(xorl %temp1,%temp1)
2519        /* We can use %ra0 as a temporary here, since the real return address */
2520        /* is on the stack   */
25210:      __(movl -node_size(%imm0),%ra0)
2522        __(movl %ra0,-node_size(%ebp,%temp1))
2523        __(subl $node_size,%imm0)
2524        __(subl $node_size,%temp1)
2525        __(cmpl %imm0,%esp)
2526        __(jne 0b)
2527        __(lea (%ebp,%temp1),%esp)
2528        __(movl 4(%ebp),%ra0)
2529        __(movl (%ebp),%ebp)
2530        __(pushl %ra0)
2531        __(movd %mm0,%nargs)
2532        __(movl rcontext(tcr.save0),%temp0)
2533        __(movss %fpzero,rcontext(tcr.save0))
2534        __(do_funcall())
2535        /* All args in regs; exactly the same as the tfuncallvsp case   */
25369:             
2537        __(leave)
2538        __(do_funcall())
2539
2540_endsubp(tfuncallgen)
2541
2542/* Some args were pushed; move them down in the frame   */
2543_spentry(tfuncallslide)
2544        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2545        __(movd %nargs,%mm0)
2546        __(xorl %temp1,%temp1)
2547        __(movl %temp0,rcontext(tcr.save0))
25480:      __(movl -node_size(%imm0),%temp0)
2549        __(movl %temp0,-node_size(%ebp,%temp1))
2550        __(subl $node_size,%imm0)
2551        __(subl $node_size,%temp1)
2552        __(cmpl %imm0,%esp)
2553        __(jne 0b)
2554        __(lea (%ebp,%temp1),%esp)
2555        __(push 4(%ebp))        /* return address */
2556        __(movl (%ebp),%ebp)
2557        __(movd %mm0,%nargs)
2558        __(movl rcontext(tcr.save0),%temp0)
2559        __(movss %fpzero,rcontext(tcr.save0))
2560        __(do_funcall())
2561_endsubp(tfuncallslide)
2562
2563/* No args were pushed; recover saved context & do funcall        */
2564_spentry(tfuncallvsp)
2565        __(leave)
2566        __(do_funcall())
2567_endsubp(tfuncallvsp)
2568
2569_spentry(tcallsymgen)
2570        __(cmpl $nargregs*node_size,%nargs)
2571        __(jbe 9f)
2572        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2573        __(movd %nargs,%mm0)
2574        __(movl %temp0,rcontext(tcr.save0))
2575        __(xorl %temp1,%temp1)  /* aka nargs */
25760:      __(movl -node_size(%imm0),%temp0)
2577        __(movl %temp0,-node_size(%ebp,%temp1))
2578        __(subl $node_size,%imm0)
2579        __(subl $node_size,%temp1)
2580        __(cmpl %imm0,%esp)
2581        __(jne 0b)
2582        __(lea (%ebp,%temp1),%esp)
2583        __(movl 4(%ebp),%temp0)
2584        __(movl (%ebp),%ebp)
2585        __(push %temp0)
2586        __(movl rcontext(tcr.save0),%temp0)
2587        __(movss %fpzero,rcontext(tcr.save0))
2588        __(movd %mm0,%nargs)
2589        __(jump_fname())
2590/* All args in regs; exactly the same as the tcallsymvsp case. */
25919:
2592        __(leave)
2593        __(jump_fname())
2594_endsubp(tcallsymgen)
2595
2596_spentry(tcallsymslide)
2597        __(movl %ebp,%imm0)
2598        __(subl %nargs,%imm0)
2599        __(addl $nargregs*node_size,%imm0)      /* new tos */
2600        __(push %imm0)
2601        __(push %arg_y)
2602        __(push %arg_z)
2603        __(push %nargs)
2604        __(lea (4-nargregs)*node_size(%esp,%nargs),%arg_y) /* src ptr */
2605        __(movl %ebp,%imm0) /* dst ptr */
2606        __(subl $fixnumone*nargregs,%nargs)
2607        __(jmp 1f)
26080:      __(subl $node_size,%arg_y)
2609        __(movl (%arg_y),%arg_z)
2610        __(subl $node_size,%imm0)
2611        __(movl %arg_z,(%imm0))
26121:      __(subl $fixnumone,%nargs)
2613        __(jge 0b)
2614        __(pop %nargs)
2615        __(pop %arg_z)
2616        __(pop %arg_y)
2617        __(pop %esp)
2618        __(push node_size(%ebp))
2619        __(movl 0(%ebp),%ebp)
2620        __(jump_fname)
2621_endsubp(tcallsymslide)
2622
2623_spentry(tcallsymvsp)
2624        __(leave)
2625        __(jump_fname())
2626_endsubp(tcallsymvsp)
2627
2628_spentry(tcallnfngen)
2629        __(cmpl $nargregs*node_size,%nargs)
2630        __(jbe 9f)
2631        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2632        __(movd %nargs,%mm0)    /* stash nargs aka temp1 */
2633        __(xorl %temp1,%temp1)
2634        __(movl %temp0,rcontext(tcr.save0))
2635        /* It's OK to use %ra0 (%temp0) as an temp here, since the */
2636        /* real return address is on the stack. */
26370:      __(movl -node_size(%imm0),%ra0)
2638        __(movl %ra0,-node_size(%ebp,%temp1))
2639        __(subl $node_size,%imm0)
2640        __(subl $node_size,%temp1)
2641        __(cmpl %imm0,%esp)
2642        __(jne 0b)
2643        __(movl rcontext(tcr.save0),%fn)
2644        __(movss %fpzero,rcontext(tcr.save0))
2645        __(lea (%ebp,%temp1),%esp)
2646        __(movl lisp_frame.savera0(%ebp),%ra0)
2647        __(movl lisp_frame.backlink(%ebp),%ebp)
2648        __(push %ra0)
2649        __(movd %mm0,%nargs)
2650        __(jmp *%fn)
26519:      /* All args in regs; exactly the same as the tcallnfnvsp case */
2652        __(movl %temp0,%fn)
2653        __(leave)
2654        __(jmp *%fn)
2655_endsubp(tcallnfngen)
2656
2657_spentry(tcallnfnslide)
2658        __(lea -nargregs*node_size(%esp,%nargs),%imm0)
2659        __(movd %nargs,%mm0)    /* save nargs aka temp1 */
2660        __(xorl %temp1,%temp1)
2661        __(movl %temp0,rcontext(tcr.save0))
2662        /* We can use %ra0 as a temporary here, since the real return address */
2663        /* is on the stack   */
26640:      __(movl -node_size(%imm0),%ra0)
2665        __(movl %ra0,-node_size(%ebp,%temp1))
2666        __(subl $node_size,%imm0)
2667        __(subl $node_size,%temp1)
2668        __(cmpl %imm0,%esp)
2669        __(jne 0b)
2670        __(movl rcontext(tcr.save0),%fn)
2671        __(lea (%ebp,%temp1),%esp)
2672        __(movl lisp_frame.savera0(%ebp),%ra0)
2673        __(movl lisp_frame.backlink(%ebp),%ebp)
2674        __(push %ra0)
2675        __(movapd %fpzero,rcontext(tcr.save0))
2676        __(movd %mm0,%nargs)
2677        __(jmp *%fn)
2678_endsubp(tcallnfnslide)
2679
2680_spentry(tcallnfnvsp)
2681        __(mov %temp0,%fn)
2682        __(leave)
2683        __(jmp *%fn)
2684_endsubp(tcallnfnvsp)
2685
2686/* Make a "raw" area on the foreign stack, stack-cons a macptr to point */
2687/* to it, and return the macptr.  Size (in bytes, boxed) is in arg_z */
2688/* on entry; macptr in arg_z on exit. */
2689_spentry(makestackblock)
2690        __(check_cstack_alignment())
2691        __(unbox_fixnum(%arg_z,%imm0))
2692        __(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
2693        __(cmpl $tstack_alloc_limit,%imm0)
2694        __(jae 1f)
2695        __(movd rcontext(tcr.foreign_sp),%mm0)
2696        __(subl %imm0,rcontext(tcr.foreign_sp))
2697        __(movl rcontext(tcr.foreign_sp),%arg_z)
2698        __(movd %mm0,(%arg_z))
2699        __(movl %ebp,csp_frame.save_ebp(%arg_z))
2700        __(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
2701        __(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
2702        __(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
2703        __(movl %imm0,macptr.address(%arg_z))
2704        __(movss %fpzero,macptr.domain(%arg_z))
2705        __(movss %fpzero,macptr.type(%arg_z))
2706        __(ret)
27071:      __(movd rcontext(tcr.foreign_sp),%mm0)
2708        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2709        __(movl rcontext(tcr.foreign_sp),%imm0)
2710        __(movd %mm0,(%imm0))
2711        __(movl %ebp,csp_frame.save_ebp(%imm0))
2712        __(set_nargs(1))
2713        __(movl $nrs.new_gcable_ptr,%fname)
2714        __(jump_fname())
2715_endsubp(makestackblock)
2716
2717_spentry(makestackblock0)
2718        __(unbox_fixnum(%arg_z,%imm0))
2719        __(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
2720        __(cmpl $tstack_alloc_limit,%imm0)
2721        __(jae 9f)
2722        __(movl rcontext(tcr.foreign_sp),%temp0)
2723        __(subl %imm0,rcontext(tcr.foreign_sp))
2724        __(movl rcontext(tcr.foreign_sp),%arg_z)
2725        __(movl %temp0,(%arg_z))
2726        __(movl %ebp,csp_frame.save_ebp(%arg_z))
2727        __(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
2728        __(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
2729        __(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
2730        __(movl %imm0,macptr.address(%arg_z))
2731        __(movss %fpzero,macptr.domain(%arg_z))
2732        __(movss %fpzero,macptr.type(%arg_z))
2733        __(jmp 2f)
27341:      __(movsd %fpzero,(%imm0))
2735        __(addl $dnode_size,%imm0)
27362:      __(cmpl %imm0,%temp0)
2737        __(jne 1b)
2738        __(repret)
27399:      __(movd rcontext(tcr.foreign_sp),%mm0)
2740        __(subl $dnode_size,rcontext(tcr.foreign_sp))
2741        __(movl rcontext(tcr.foreign_sp),%imm0)
2742        __(movd %mm0,(%imm0))
2743        __(movl %ebp,csp_frame.save_ebp(%imm0))
2744        __(set_nargs(1))
2745        __(movl $nrs.new_gcable_ptr,%fname)
2746        __(jump_fname())
2747_endsubp(makestackblock0)
2748
2749_spentry(makestacklist)
2750        __(test %arg_y,%arg_y)
2751        __(js 9f)
2752        __(movl %arg_y,%imm0)
2753        __(testb $fixnummask,%imm0_b)
2754        __(jne 9f)
2755        __(addl %imm0,%imm0)
2756        __(rcmpl(%imm0,$tstack_alloc_limit))
2757        __(movl $nil_value,%temp1) 
2758        __(jae 2f)
2759        __(addl $tsp_frame.fixed_overhead,%imm0)
2760        __(TSP_Alloc_Var(%imm0,%temp0))
2761        __(addl $fulltag_cons,%temp0)
2762        __(jmp 1f)
27630:      __(_rplaca(%temp0,%arg_z))
2764        __(_rplacd(%temp0,%temp1))
2765        __(movl %temp0,%temp1)
2766        __(addl $cons.size,%temp0)
27671:      __(subl $fixnumone,%arg_y)
2768        __(jge 0b)
2769        __(movl %temp1,%arg_z)
2770        __(ret)
27712:      __(TSP_Alloc_Fixed(0,%imm0))
2772        __(jmp 4f)
27733:      __(Cons(%arg_z,%temp1,%temp1))
27744:      __(subl $fixnumone,%arg_y)                             
2775        __(jge 3b)
2776        __(movl %temp1,%arg_z)
2777        __(ret)
27789:      __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte))
2779_endsubp(makestacklist)
2780
2781/* subtype (boxed) vpushed before initial values. (Had better be a */
2782/* node header subtag.)  Nargs set to count of things vpushed. */
2783_spentry(stkgvector)
2784        __(movl -fixnumone(%esp,%nargs),%imm0)  /* boxed subtag */
2785        __(shrl $fixnumshift,%imm0)
2786        __(leal -fixnumone(%nargs),%arg_z)
2787        __(movl %arg_z,%arg_y)
2788        __(shll $num_subtag_bits-fixnumshift,%arg_z)
2789        __(orl %arg_z,%imm0)    /* imm0 = header, %arg_y = unaligned size */
2790        __(movd %imm0,%mm0)
2791        __(dnode_align(%arg_y,(tsp_frame.fixed_overhead+node_size),%imm0))
2792        __(TSP_Alloc_Var(%imm0,%arg_z))
2793        __(movd %mm0,(%arg_z))
2794        __(addl $fulltag_misc,%arg_z)
2795        __(lea -node_size(%nargs),%imm0)
2796        __(jmp 2f)
27971:      __(pop misc_data_offset(%arg_z,%imm0))
27982:      __(subl $node_size,%imm0)
2799        __(jge 1b)
2800        __(addl $node_size,%esp)
2801        __(jmp *%ra0)
2802_endsubp(stkgvector)
2803
2804/* Allocate a fulltag-misc object. */
2805/* arg_y = boxed element count, arg_z = subtag (boxed, of course) */
2806_spentry(misc_alloc)
2807        __(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
2808        __(jne local_label(misc_alloc_not_u24))
2809        __(unbox_fixnum(%arg_z,%imm0))
2810        __(mov %arg_y,%temp0)
2811        __(shl $num_subtag_bits-fixnumshift,%temp0)
2812        __(or %temp0,%imm0)     /* %imm0 now = header */
2813        __(movd %imm0,%mm0)     /* Misc_Alloc wants header in %mm0 */
2814        __(andb $fulltagmask,%imm0_b)
2815        __(cmpb $fulltag_nodeheader,%imm0_b)
2816        __(je local_label(misc_alloc_32))
2817        __(movd %mm0,%imm0)
2818        __(cmpb $max_32_bit_ivector_subtag,%imm0_b)
2819        __(jbe local_label(misc_alloc_32))
2820        __(cmpb $max_8_bit_ivector_subtag,%imm0_b)
2821        __(jbe local_label(misc_alloc_8))
2822        __(cmpb $max_16_bit_ivector_subtag,%imm0_b)
2823        __(jbe local_label(misc_alloc_16))
2824        __(cmpb $subtag_double_float_vector,%imm0_b)
2825        __(jne local_label(misc_alloc_1))
2826        /* double-float vector case */
2827        __(imul $2,%arg_y,%imm0)
2828        __(jmp local_label(misc_alloc_alloc_vector))
2829local_label(misc_alloc_1):
2830        __(unbox_fixnum(%arg_y,%imm0))
2831        __(addl $7,%imm0)
2832        __(shrl $3,%imm0)
2833        __(jmp local_label(misc_alloc_alloc_vector))
2834local_label(misc_alloc_8):
2835        __(unbox_fixnum(%arg_y,%imm0))
2836        __(jmp local_label(misc_alloc_alloc_vector))
2837local_label(misc_alloc_16):
2838        __(unbox_fixnum(%arg_y,%imm0))
2839        __(shl $1,%imm0)
2840        __(jmp local_label(misc_alloc_alloc_vector))
2841local_label(misc_alloc_32):
2842        __(movl %arg_y,%imm0)
2843local_label(misc_alloc_alloc_vector):
2844        __(dnode_align(%imm0,node_size,%imm0))
2845        __(Misc_Alloc(%arg_z))
2846        __(ret)
2847local_label(misc_alloc_not_u24):
2848        __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_24))
2849_endsubp(misc_alloc)
2850
2851/* N.B. arg count word in %imm0, not %nargs */
2852/* no %whole_reg;  it's in rcontext(tcr.save0) */
2853/* %arg_reg is %temp1, key vector in %arg_y */
2854_startfn(C(destbind1))
2855        __(movl %ra0,rcontext(tcr.save1))
2856        /* Save entry %esp in case of error   */
2857        __(movd %esp,%mm0)
2858        /* Save arg count word */
2859        __(movd %imm0,%mm1)
2860        /* Extract required arg count.   */
2861        __(testb %imm0_b,%imm0_b)
2862        __(je local_label(opt))         /* skip if no required args   */
2863        __(movzbl %imm0_b,%imm0)
2864local_label(req_loop): 
2865        __(compare_reg_to_nil(%arg_reg))
2866        __(je local_label(toofew))
2867        __(movb $fulltagmask,%imm0_bh)
2868        __(andb %arg_reg_b,%imm0_bh)
2869        __(cmpb $fulltag_cons,%imm0_bh)
2870        __(jne local_label(badlist))
2871        __(subb $1,%imm0_b)
2872        __(pushl cons.car(%arg_reg))
2873        __(_cdr(%arg_reg,%arg_reg))
2874        __(jne local_label(req_loop))
2875        __(movd %mm1,%imm0)
2876local_label(opt):
2877        __(testb %imm0_bh,%imm0_bh)
2878        __(je local_label(rest_keys))
2879        __(btl $initopt_bit,%imm0)
2880        __(jc local_label(opt_supp))
2881        /* 'simple' &optionals:  no supplied-p, default to nil.   */
2882local_label(simple_opt_loop):
2883        __(compare_reg_to_nil(%arg_reg))
2884        __(je local_label(default_simple_opt))
2885        __(movb $fulltagmask,%imm0_bh)
2886        __(andb %arg_reg_b,%imm0_bh)
2887        __(cmpb $fulltag_cons,%imm0_bh)
2888        __(jne local_label(badlist))
2889        __(subb $1,%imm0_b)
2890        __(pushl cons.car(%arg_reg))
2891        __(_cdr(%arg_reg,%arg_reg))
2892        __(jne local_label(simple_opt_loop))
2893        __(jmp local_label(rest_keys))
2894local_label(default_simple_opt):
2895        __(subb $1,%imm0_b)
2896        __(pushl $nil_value)
2897        __(jne local_label(default_simple_opt))
2898        __(jmp local_label(rest_keys))
2899local_label(opt_supp):
2900        __(movb $fulltagmask,%imm0_bh)
2901        __(andb %arg_reg_b,%imm0_bh)
2902        __(compare_reg_to_nil(%arg_z))
2903        __(je local_label(default_hard_opt))
2904        __(cmpb $fulltag_cons,%imm0_bh)
2905        __(jne local_label(badlist))
2906        __(subb $1,%imm0_b)
2907        __(pushl cons.car(%arg_reg))
2908        __(_cdr(%arg_reg,%arg_reg))
2909        __(push $t_value)
2910        __(jne local_label(opt_supp))
2911        __(jmp local_label(rest_keys))
2912local_label(default_hard_opt):
2913        __(subb $1,%imm0_b)
2914        __(push $nil_value)
2915        __(push $nil_value)
2916        __(jne local_label(default_hard_opt))
2917local_label(rest_keys):
2918        __(btl $restp_bit,%imm0)
2919        __(jc local_label(have_rest))
2920        __(btl $keyp_bit,%imm0)
2921        __(jc local_label(have_keys))
2922        __(compare_reg_to_nil(%arg_reg))
2923        __(jne local_label(toomany))
2924        __(movss %fpzero,rcontext(tcr.save0))
2925        __(jmp *%ra0)
2926local_label(have_rest):
2927        __(pushl %arg_reg)
2928        __(btl $keyp_bit,%imm0)
2929        __(jc local_label(have_keys))
2930        __(movss %fpzero,rcontext(tcr.save0))
2931        __(jmp *%ra0)
2932        /* Ensure that arg_reg contains a proper,even-length list.  */
2933        /* Insist that its length is <= 512 (as a cheap circularity check.)   */
2934local_label(have_keys):
2935        __(movb $255,%imm0_b)
2936        __(push %arg_reg)
2937        __(push %arg_z)
2938        __(xorl %arg_z,%arg_z)
2939local_label(count_keys_loop):
2940        __(compare_reg_to_nil(%arg_reg))
2941        __(je local_label(counted_keys))
2942        __(subb $1,%imm0_b)
2943        __(jb local_label(toomany))
2944        __(movb $fulltagmask,%arg_z_bh)
2945        __(andb %arg_reg_b,%arg_z_bh)
2946        __(cmpb $fulltag_cons,%arg_z_bh)
2947        __(jne local_label(badlist))
2948        __(_cdr(%arg_reg,%arg_reg))
2949        __(movb $fulltagmask,%arg_z_bh)
2950        __(andb %arg_reg_b,%arg_z_bh)
2951        __(cmpb $fulltag_cons,%arg_z_bh)
2952        __(jne local_label(badlist))
2953        __(_cdr(%arg_reg,%arg_reg))
2954        __(jmp local_label(count_keys_loop))
2955local_label(counted_keys):             
2956        /* We've got a proper, even-length list of key/value pairs in  */
2957        /* arg_reg. For each keyword var in the lambda-list, push a pair  */
2958        /* of NILs on the vstack.   */
2959        __(pop %arg_z)
2960        __(pop %arg_reg)
2961        __(movd %mm1,%imm0)
2962        __(shrl $16,%imm0)
2963        __(movzbl %imm0_b,%imm0)
2964        __(movl %esp,rcontext(tcr.unboxed0))    /* 0th value/supplied-p pair */
2965        __(jmp local_label(push_pair_test))
2966local_label(push_pair_loop):
2967        __(push $nil_value)
2968        __(push $nil_value)
2969local_label(push_pair_test):   
2970        __(subb $1,%imm0_b)
2971        __(jge local_label(push_pair_loop))
2972        __(push %temp0) /* keyword */
2973        __(push %arg_z) /* value */
2974        __(vector_length(%arg_y,%imm0))
2975        __(push %arg_reg)
2976        __(push %imm0)  /* keyword vector length */
2977        __(movd %mm1,%imm0)
2978        __(movl $0,rcontext(tcr.unboxed1)) /* count of unknown keywords seen */
2979local_label(match_keys_loop):
2980        __(movl 4(%esp),%arg_reg)
2981        __(compare_reg_to_nil(%arg_reg))
2982        __(je local_label(matched_keys))
2983        __(_car(%arg_reg,%temp0))
2984        __(_cdr(%arg_reg,%arg_reg))
2985        __(_car(%arg_reg,%arg_z))
2986        __(_cdr(%arg_reg,%arg_reg))
2987        __(movl %arg_reg,4(%esp))
2988        __(xorl %temp1,%temp1)
2989        __(jmp local_label(match_test))
2990local_label(match_loop):
2991        __(cmpl misc_data_offset(%arg_y,%temp1),%arg_z)
2992        __(je local_label(matched))
2993        __(addl $node_size,%temp1)
2994local_label(match_test):
2995        __(cmpl %temp1,(%esp))  /* compare index, keyword vector length */
2996        __(jne local_label(match_loop))
2997        /* No match.  Note unknown keyword, check for :allow-other-keys   */
2998        __(addl $1,rcontext(tcr.unboxed1))
2999        __(cmpl $nrs.kallowotherkeys,%temp0)
3000        __(jne local_label(match_keys_loop))
3001        __(subl $1,rcontext(tcr.unboxed1))
3002        __(btsl $seen_aok_bit,%imm0)
3003        __(jc local_label(match_keys_loop))
3004        /* First time we've seen :allow-other-keys.  Maybe set aok_bit.   */
3005        __(compare_reg_to_nil(%arg_z))
3006        __(je local_label(match_keys_loop))
3007        __(btsl $aok_bit,%imm0)
3008        __(jmp local_label(match_keys_loop))
3009        /* Got a match.  Worry about :allow-other-keys here, too.   */
3010local_label(matched):
3011        __(negl %temp1)
3012        __(shll $1,%temp1)
3013        __(addl rcontext(tcr.unboxed0),%temp1)
3014        __(cmpl $nil_value,-node_size*2(%temp1))
3015        __(jne local_label(match_keys_loop))
3016        __(movl %arg_z,-node_size(%temp1))
3017        __(movl $t_value,-node_size*2(%temp1))
3018        __(cmpl $nrs.kallowotherkeys,%temp0)
3019        __(jne local_label(match_keys_loop))
3020        __(btsl $seen_aok_bit,%imm0)
3021        __(jnc local_label(match_keys_loop))
3022        __(compare_reg_to_nil(%arg_z))
3023        __(je local_label(match_keys_loop))
3024        __(btsl $aok_bit,%imm0)
3025        __(jmp local_label(match_keys_loop))
3026local_label(matched_keys):     
3027        __(cmpl $0,rcontext(tcr.unboxed1))      /* any unknown keys seen? */
3028        __(je local_label(keys_ok))
3029        __(btl $aok_bit,%imm0)
3030        __(jnc local_label(badkeys))
3031local_label(keys_ok):
3032        __(addl $(3*node_size),%esp)
3033        __(pop %ra0)
3034        __(movss %fpzero,rcontext(tcr.save0))
3035        __(jmp *%ra0)
3036        /* Some unrecognized keywords.  Complain generically about   */
3037        /* invalid keywords.   */
3038local_label(badkeys):
3039        __(movl $XBADKEYS,%arg_y)
3040        __(jmp local_label(destructure_error))
3041local_label(toomany):
3042        __(movl $XCALLTOOMANY,%arg_y)
3043        __(jmp local_label(destructure_error))
3044local_label(toofew):
3045        __(movl $XCALLTOOFEW,%arg_y)
3046        __(jmp local_label(destructure_error))
3047local_label(badlist):
3048        __(movl $XCALLNOMATCH,%arg_y)
3049local_label(destructure_error):
3050        __(movd %mm0,%esp)              /* undo everything done to the stack */
3051        __(movl rcontext(tcr.save0),%arg_z)     /* %whole_reg */
3052        __(movss %fpzero,rcontext(tcr.save0))
3053        __(set_nargs(2))
3054        __(push %ra0)
3055        __(jmp _SPksignalerr)
3056_endfn(C(destbind1))
3057
3058_spentry(macro_bind)
3059        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3060        __(extract_fulltag(%arg_reg,%imm0))
3061        __(cmpb $fulltag_cons,%imm0_b)
3062        __(jne 1f)
3063        __(_cdr(%arg_reg,%arg_reg))
3064        __(jmp C(destbind1))
30651:      __(movl $XCALLNOMATCH,%arg_y)
3066        __(movl rcontext(tcr.save0),%arg_z)
3067        __(movss %fpzero,rcontext(tcr.save0))
3068        __(set_nargs(2))
3069        __(push %ra0)       
3070        __(jmp _SPksignalerr)
3071
3072_endsubp(macro_bind)
3073
3074_spentry(destructuring_bind)
3075        __(movl %arg_reg,rcontext(tcr.save0))   /* %whole_reg */
3076        __(jmp C(destbind1))
3077_endsubp(destructuring_bind)
3078
3079_spentry(destructuring_bind_inner)
3080        __(movl %arg_z,rcontext(tcr.save0))     /* %whole_reg */
3081        __(jmp C(destbind1))
3082_endsubp(destructuring_bind_inner)
3083
3084_spentry(vpopargregs)
3085        __(int $3)
3086_endsubp(vpopargregs)
3087
3088/* If arg_z is an integer, return in imm0 something whose sign  */
3089/* is the same as arg_z's.  If not an integer, error.   */
3090_spentry(integer_sign)
3091        __(mov %arg_z,%imm0)
3092        __(testb $tagmask,%arg_z_b)
3093        __(je 8f)
3094        __(extract_typecode(%arg_z,%imm0))
3095        __(cmpb $subtag_bignum,%imm0_b)
3096        __(jne 9f)
3097        __(getvheader(%arg_z,%imm0))
3098        __(shr $num_subtag_bits,%imm0)
3099        __(movl misc_data_offset-4(%arg_z,%imm0,4),%imm0)
31008:      __(repret)
31019:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_integer))
3102_endsubp(integer_sign)
3103
3104/* "slide" nargs worth of values up the stack.  imm0 contains */
3105/* the difference between the current stack pointer and the target. */
3106_spentry(mvslide)
3107        __(movd %nargs,%mm0)
3108        __(lea (%esp,%nargs),%arg_y)
3109        __(lea (%arg_y,%imm0),%imm0)
3110        __(test %nargs,%nargs)
3111        __(je 2f)
31121:
3113        __(subl $node_size,%arg_y)
3114        __(movl (%arg_y),%arg_z)
3115        __(subl $node_size,%imm0)
3116        __(movl %arg_z,(%imm0))
3117        __(subl $node_size,%nargs)
3118        __(jne 1b)
31192:      __(movl %imm0,%esp)
3120        __(movd %mm0,%nargs)
3121        __(jmp *%ra0)
3122_endsubp(mvslide)
3123
3124_spentry(save_values)
3125        __(movd rcontext(tcr.save_tsp),%mm1)
3126/* common exit: nargs = values in this set, mm1 = ptr to tsp before call to save_values   */
3127local_label(save_values_to_tsp):
3128        __(movl %ra0,rcontext(tcr.save0))
3129        __(movl rcontext(tcr.save_tsp),%temp0)
3130        __(dnode_align(%nargs,tsp_frame.fixed_overhead+(2*node_size),%imm0)) /* count, link   */
3131        __(TSP_Alloc_Var(%imm0,%arg_z))
3132        __(movl rcontext(tcr.save_tsp),%imm0)
3133        __(movd %mm1,(%imm0))
3134        __(movl %nargs,(%arg_z))
3135        __(movl %temp0,node_size(%arg_z))
3136        __(leal 2*node_size(%arg_z,%nargs),%arg_y)
3137        __(leal (%esp,%nargs),%imm0)
3138        __(cmpl %imm0,%esp)
3139        __(jmp 2f)
31401:      __(subl $node_size,%imm0)
3141        __(movl (%imm0),%arg_z)
3142        __(subl $node_size,%arg_y)
3143        __(cmpl %imm0,%esp)
3144        __(movl %arg_z,(%arg_y))
31452:      __(jne 1b)
3146        __(addl %nargs,%esp)
3147        __(movl rcontext(tcr.save0),%ra0)
3148        __(movl $0,rcontext(tcr.save0))
3149        __(jmp *%ra0)
3150_endsubp(save_values)
3151
3152/* Add the multiple values that are on top of the vstack to the set  */
3153/* saved in the top tsp frame, popping them off of the vstack in the  */
3154/* process.  It is an error (a bad one) if the TSP contains something  */
3155/* other than a previously saved set of multiple-values.  */
3156/* Since adding to the TSP may cause a new TSP segment to be allocated,  */
3157/* each add_values call adds another linked element to the list of  */
3158/* values. This makes recover_values harder.   */
3159_spentry(add_values)
3160        /* do we need to preserve imm0? */
3161        __(test %nargs,%nargs)
3162        __(movl rcontext(tcr.save_tsp),%imm0)
3163        __(movl (%imm0),%imm0)
3164        __(movd %imm0,%mm1)     /* for the benefit of save_values_to_tsp */
3165        __(jne local_label(save_values_to_tsp))
3166        __(jmp *%ra0)
3167_endsubp(add_values)
3168
3169/* push the values in the value set atop the sp, incrementing nargs.  */
3170/* Discard the tsp frame; leave values atop the sp.   */
3171_spentry(recover_values)
3172        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3173        __(movd %nargs,%mm0)              /* temp1 */
3174        /* First, walk the segments reversing the pointer to previous  */
3175        /* segment pointers Can tell the end because that previous  */
3176        /* segment pointer is the prev tsp pointer   */
3177        __(movl rcontext(tcr.save_tsp),%temp1)
3178        __(movl %temp1,%temp0)  /* current segment   */
3179        __(movl %temp1,%arg_y)  /* last segment   */
3180        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3181local_label(walkloop):
3182        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3183        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3184        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3185        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3186        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3187        __(jne local_label(walkloop))
3188
3189        __(movl %temp1,%arg_z)
3190        __(movd %mm0,%nargs)
3191        /* the final segment pointer is now in %arg_y  */
3192        /* walk backwards, pushing values on the stack and incrementing %nargs   */
3193local_label(pushloop):
3194        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment   */
3195        __(test %imm0,%imm0)
3196        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3197        __(leal (%nargs,%imm0),%nargs)
3198        __(jmp 2f)
31991:      __(push -node_size(%temp0))
3200        __(subl $node_size,%temp0)
3201        __(subl $fixnum_one,%imm0)
32022:      __(jne 1b)
3203        __(cmpl %arg_y,%arg_z)
3204        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3205        __(jne local_label(pushloop))
3206        __(movl (%arg_z),%arg_z)
3207        __(movl %arg_z,rcontext(tcr.save_tsp))
3208        __(movl %arg_z,rcontext(tcr.next_tsp))
3209        __(movl rcontext(tcr.save0),%ra0)
3210        __(movl $0,rcontext(tcr.save0))
3211        __(jmp *%ra0)           
3212_endsubp(recover_values)
3213
3214/* Exactly like recover_values, but it's necessary to reserve an outgoing  */
3215/* frame if any values (which will be used as outgoing arguments) will  */
3216/* wind up on the stack.  We can assume that %nargs contains 0 (and  */
3217/* that no other arguments have been pushed) on entry.   */
3218
3219_spentry(recover_values_for_mvcall)
3220        __(movl %ra0,rcontext(tcr.save0)) /* temp0 */
3221        /* First, walk the segments reversing the pointer to previous  */
3222        /* segment pointers Can tell the end because that previous  */
3223        /* segment pointer is the prev tsp pointer   */
3224        __(xorl %nargs,%nargs)
3225        __(push %nargs)
3226        __(movl rcontext(tcr.save_tsp),%temp1)
3227        __(movl %temp1,%temp0)  /* current segment   */
3228        __(movl %temp1,%arg_y)  /* last segment   */
3229        __(movl tsp_frame.backlink(%temp1),%arg_z)      /* previous tsp   */
3230local_label(walkloop_mvcall):
3231        __(movl tsp_frame.data_offset(%temp0),%imm0)
3232        __(addl %imm0,(%esp))
3233        __(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
3234        __(cmpl %imm0,%arg_z)   /* last segment ?   */
3235        __(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
3236        __(movl %temp0,%arg_y)  /* last segment <- current segment   */
3237        __(movl %imm0,%temp0)   /* current segment <- next segment   */
3238        __(jne local_label(walkloop_mvcall))
3239
3240        __(movl %temp1,%arg_z)
3241        __(pop %nargs)
3242
3243        __(cmpl $nargregs*node_size,%nargs)
3244        __(jbe local_label(pushloop_mvcall))
3245        __(push $reserved_frame_marker)
3246        __(push $reserved_frame_marker)
3247
3248        /* the final segment pointer is now in %arg_y  */
3249        /* walk backwards, pushing values on the stack and incrementing %nargs*/
3250local_label(pushloop_mvcall):
3251        __(movl tsp_frame.data_offset(%arg_y),%imm0)    /* nargs in segment */
3252        __(test %imm0,%imm0)
3253        __(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
3254        __(jmp 2f)
32551:      __(push -node_size(%temp0))
3256        __(subl $node_size,%temp0)
3257        __(subl $fixnum_one,%imm0)
32582:      __(jne 1b)
3259        __(cmpl %arg_y,%arg_z)
3260        __(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
3261        __(jne local_label(pushloop_mvcall))
3262        __(movl (%arg_z),%arg_z)
3263        __(movl %arg_z,rcontext(tcr.save_tsp))
3264        __(movl %arg_z,rcontext(tcr.next_tsp))
3265        __(movl rcontext(tcr.save0),%ra0)
3266        __(movl $0,rcontext(tcr.save0))
3267        __(jmp *%ra0)           
3268_endsubp(recover_values_for_mvcall)
3269
3270_spentry(reset)
3271        __(int $3)
3272_endsubp(reset)
3273
3274/* temp0 = element-count, arg_y = subtag, arg_z = initval */
3275_spentry(misc_alloc_init)
3276        __(push %ebp)
3277        __(movl %esp,%ebp)
3278        __(push %arg_z)
3279        __(movl %arg_y,%arg_z)
3280        __(movl %temp0,%arg_y)
3281        __(push $local_label(misc_alloc_init_back))
3282        __(jmp _SPmisc_alloc)
3283__(tra(local_label(misc_alloc_init_back)))
3284        __(pop %arg_y)
3285        __(leave)
3286        __(movl $nrs.init_misc,%fname)
3287        __(set_nargs(2))
3288        __(jump_fname())
3289_endsubp(misc_alloc_init)
3290
3291_spentry(stack_misc_alloc_init)
3292        __(int $3)
3293_endsubp(stack_misc_alloc_init)
3294
3295        .globl C(popj)
3296_spentry(popj)
3297C(popj):
3298        __(leave)
3299        __(ret)
3300_endsubp(popj)
3301
3302/* arg_z should be of type (signed-byte 64) */
3303/* return unboxed value in mm0 */
3304_spentry(gets64)
3305        __(testb $fixnummask,%arg_z_b)
3306        __(jne 1f)
3307        __(unbox_fixnum(%arg_z,%imm0))
3308        __(movd %imm0,%mm0)
3309        __(jns 8f)
3310        /* get sign into upper half of %mm0 */
3311        __(pcmpeqd %mm1,%mm1)   /* all ones */
3312        __(psllq $32,%mm1)
3313        __(por %mm1,%mm0)
3314        __(ret)
33151:      __(movb %arg_z_b,%imm0_b)
3316        __(andb $tagmask,%imm0_b)
3317        __(cmpb $tag_misc,%imm0_b)
3318        __(jne 9f)
3319        __(movl misc_header_offset(%arg_z),%imm0)
3320        __(cmpb $subtag_bignum,%imm0_b)
3321        __(jne 9f)
3322        __(cmpl $two_digit_bignum_header,%imm0)
3323        __(ja 9f)
3324        __(movd misc_data_offset(%arg_z),%mm0)
3325        __(jne 8f)
3326        __(movq misc_data_offset(%arg_z),%mm0)
33278:      __(repret)
33289:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_s64))
3329_endsubp(gets64)
3330
3331/* arg_z should be of type (unsigned-byte 64) */
3332/* return unboxed value in mm0 */
3333_spentry(getu64)
3334        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3335        __(testl %arg_z,%imm0)
3336        __(movl %arg_z,%imm0)
3337        __(jne 1f)
3338        __(sarl $fixnumshift,%imm0)
3339        __(movd %imm0,%mm0)
3340        __(ret)
33411:      __(andb $tagmask,%imm0_b)
3342        __(cmpb $tag_misc,%imm0_b)
3343        __(jne 9f)
3344        __(movl misc_header_offset(%arg_z),%imm0)
3345        __(cmpb $subtag_bignum,%imm0_b)
3346        __(jne 9f)
3347        __(cmpl $three_digit_bignum_header,%imm0)
3348        __(ja 9f)
3349        __(je 3f)
3350        __(cmpl $two_digit_bignum_header,%imm0)
3351        __(je 2f)
3352        /* must be a one digit bignum */
3353        __(movl misc_data_offset(%arg_z),%imm0)
3354        __(test %imm0,%imm0)
3355        __(js 9f)
3356        __(movd %imm0,%mm0)
3357        __(ret)
33582:      __(movl misc_data_offset+4(%arg_z),%imm0)
3359        __(testl %imm0,%imm0)
3360        __(js 9f)
3361        __(movq misc_data_offset(%arg_z),%mm0)
3362        __(ret)
33633:      __(movl misc_data_offset(%arg_z),%imm0)
3364        __(cmpl $0,misc_data_offset+8(%arg_z))
3365        __(jne 9f)
3366        __(movq misc_data_offset(%arg_z),%mm0)
3367        __(repret)
33689:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_u64))
3369_endsubp(getu64)
3370
3371/* Make unsigned integer from value in mm0 */
3372_spentry(makeu64)
3373        __(movq %mm0,%mm1)
3374        __(psrlq $32,%mm0)
3375        __(movd %mm0,%imm0)
3376        __(test %imm0,%imm0)
3377        __(js 3f)
3378        __(jnz 2f)
3379        __(movd %mm1,%imm0)
3380        __(cmpl $target_most_positive_fixnum,%imm0)
3381        __(ja 1f)
3382        __(box_fixnum(%imm0,%arg_z))
3383        __(ret)
33841:      /* maybe make a 1 digit bignum */
3385        __(test %imm0,%imm0)
3386        __(js 2f)
3387        __(movl $one_digit_bignum_header,%imm0)
3388        __(movd %imm0,%mm0)
3389        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3390        __(movd %mm1,misc_data_offset(%arg_z))
3391        __(ret)
3392        /* make a 2 digit bignum */
33932:      __(movl $two_digit_bignum_header,%imm0)
3394        __(movd %imm0,%mm0)
3395        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3396        __(movq %mm1,misc_data_offset(%arg_z))
3397        __(ret)
3398        /* make a 3 digit bignum */
33993:      __(movl $three_digit_bignum_header,%imm0)
3400        __(movd %imm0,%mm0)
3401        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(3)))
3402        __(movq %mm1,misc_data_offset(%arg_z))
3403        __(ret)
3404_endsubp(makeu64)
3405
3406/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
3407/* unbound_marker), arg_y = symbol */
3408_spentry(specref)
3409        __(movl symbol.binding_index(%arg_z),%imm0)
3410        __(cmp rcontext(tcr.tlb_limit),%imm0)
3411        __(movl rcontext(tcr.tlb_pointer),%temp1)
3412        __(movl %arg_z,%arg_y)
3413        __(jae 7f)
3414        __(movl (%temp1,%imm0),%arg_z)
3415        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3416        __(jne 8f)
34177:      __(movl symbol.vcell(%arg_y),%arg_z)
34188:      __(repret)             
3419_endsubp(specref)
3420
3421/* arg_y = special symbol, arg_z = new value. */
3422_spentry(specset)
3423        __(movl symbol.binding_index(%arg_y),%imm0)
3424        __(cmp rcontext(tcr.tlb_limit),%imm0)
3425        __(movl rcontext(tcr.tlb_pointer),%temp1)
3426        __(jae 1f)
3427        __(movl (%temp1,%imm0),%temp0)
3428        __(cmpb $no_thread_local_binding_marker,%temp0_b)
3429        __(je 1f)
3430        __(movl %arg_z,(%temp1,%imm0))
3431        __(ret)
34321:      __(movl %arg_y,%temp0)
3433        __(movl $1<<fixnumshift,%arg_y)
3434        __(jmp _SPgvset)
3435_endsubp(specset)
3436
3437_spentry(specrefcheck)
3438        __(mov %arg_z,%arg_y)
3439        __(movl symbol.binding_index(%arg_z),%imm0)
3440        __(cmp rcontext(tcr.tlb_limit),%imm0)
3441        __(jae 7f)
3442        __(movl rcontext(tcr.tlb_pointer),%temp1)
3443        __(movl (%temp1,%imm0),%arg_z)
3444        __(cmpb $no_thread_local_binding_marker,%arg_z_b)
3445        __(jne 8f)
34467:      __(movl symbol.vcell(%arg_y),%arg_z)
34478:      __(cmpb $unbound_marker,%arg_z_b)
3448        __(jne 9f)
3449        __(uuo_error_reg_unbound(Rarg_y))
34509:      __(repret)
3451_endsubp(specrefcheck)
3452
3453_spentry(restoreintlevel)
3454        __(int $3)
3455_endsubp(restoreintlevel)
3456
3457/* Make a lisp integer from the unsigned value in imm0 */
3458_spentry(makeu32)
3459        __(cmpl $target_most_positive_fixnum,%imm0)
3460        __(ja 0f)       /* need to make a bignum */
3461        __(box_fixnum(%imm0,%arg_z))
3462        __(ret)
34630:      __(movd %imm0,%mm1)
3464        __(test %imm0,%imm0)
3465        __(js 1f)
3466        __(movl $one_digit_bignum_header,%imm0)
3467        __(movd %imm0,%mm0)
3468        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
3469        __(movd %mm1,misc_data_offset(%arg_z))
3470        __(ret)
34711:      __(movl $two_digit_bignum_header,%imm0)
3472        __(movd %imm0,%mm0)
3473        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
3474        __(movd %mm1,misc_data_offset(%arg_z))
3475        __(ret)
3476_endsubp(makeu32)
3477
3478/* arg_z is of type (signed-byte 32) */
3479/* return unboxed value in %imm0 */
3480_spentry(gets32)
3481        __(testb $fixnummask,%arg_z_b)
3482        __(jne 1f)
3483        __(unbox_fixnum(%arg_z,%imm0))
3484        __(ret)
34851:      __(movb %arg_z_b,%imm0_b)
3486        __(andb $tagmask,%imm0_b)
3487        __(cmpb $tag_misc,%imm0_b)
3488        __(jne 9f)
3489        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3490        __(cmpb $subtag_bignum,%imm0_b)
3491        __(jne 9f)
3492        __(movl misc_header_offset(%arg_z),%imm0)
3493        __(cmpl $one_digit_bignum_header,%imm0)
3494        __(jne 9f)
3495        __(movl misc_data_offset(%arg_z),%imm0)
3496        __(ret)
34979:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_signed_byte_32))
3498_endsubp(gets32)
3499
3500/* arg_z is of type (unsigned-byte 32) */
3501/* return unboxed value in %imm0 */
3502_spentry(getu32)
3503        __(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
3504        __(testl %arg_z,%imm0)
3505        __(movl %arg_z,%imm0)
3506        __(jne 1f)
3507        __(sarl $fixnumshift,%imm0)
3508        __(ret)
35091:      __(andb $tagmask,%imm0_b)
3510        __(cmpb $tag_misc,%imm0_b)
3511        __(jne 9f)
3512        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3513        __(cmpb $subtag_bignum,%imm0_b)
3514        __(jne 9f)
3515        __(movl misc_header_offset(%arg_z),%imm0)
3516        __(cmpl $two_digit_bignum_header,%imm0)
3517        __(je 2f)
3518        __(cmpl $one_digit_bignum_header,%imm0)
3519        __(jne 9f)
3520        __(movl misc_data_offset(%arg_z),%imm0)
3521        __(ret)
35222:      __(movl misc_data_offset(%arg_z),%imm0)
3523        __(cmpl $0,misc_data_offset+4(%arg_z))
3524        __(jne 9f)
3525        __(ret)
35269:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_unsigned_byte_32))
3527_endsubp(getu32)
3528
3529_spentry(mvpasssym)
3530        __(int $3)
3531_endsubp(mvpasssym)
3532
3533/* don't smash arg_z */
3534_spentry(unbind)
3535        __(push %arg_z)
3536        __(movl rcontext(tcr.db_link),%imm0)
3537        __(movl rcontext(tcr.tlb_pointer),%arg_z)
3538        __(movl binding.sym(%imm0),%temp0)
3539        __(movl binding.val(%imm0),%arg_y)
3540        __(movl binding.link(%imm0),%imm0)
3541        __(movl %arg_y,(%arg_z,%temp0))
3542        __(movl %imm0,rcontext(tcr.db_link))
3543        __(pop %arg_z)
3544        __(ret)
3545_endsubp(unbind)
3546
3547_spentry(unbind_n)
3548        __(push %temp1)         /* preserve temp1/nargs */
3549        __(push %arg_z)
3550        __(xorl %arg_z,%arg_z)
3551        __(movl rcontext(tcr.db_link),%temp1)
3552        __(movl rcontext(tcr.tlb_pointer),%arg_z)
35531:             
3554        __(movl binding.sym(%temp1),%temp0)
3555        __(movl binding.val(%temp1),%arg_y)
3556        __(movl binding.link(%temp1),%temp1)
3557        __(movl %arg_y,(%arg_z,%temp0))
3558        __(decl %imm0)
3559        __(jne 1b)
3560        __(movl %temp1,rcontext(tcr.db_link))
3561        __(pop %arg_z)
3562        __(pop %temp1)
3563        __(ret) 
3564_endsubp(unbind_n)
3565
3566_spentry(unbind_to)
3567        __(push %arg_y)
3568        __(push %arg_z)
3569        __(push %temp0)
3570        __(push %temp1)
3571       
3572        __(movl rcontext(tcr.db_link),%temp0)
3573        __(movl rcontext(tcr.tlb_pointer),%arg_z)
35741:
3575        __(movl binding.sym(%temp0),%temp1)
3576        __(movl binding.val(%temp0),%arg_y)
3577        __(movl binding.link(%temp0),%temp0)
3578        __(movl %arg_y,(%arg_z,%temp1))
3579        __(cmpl %temp0,%imm0)
3580        __(jne 1b)
3581        __(movl %temp0,rcontext(tcr.db_link))
3582
3583        __(pop %temp1)
3584        __(pop %temp0)
3585        __(pop %arg_z)
3586        __(pop %arg_y)
3587        __(ret)
3588_endsubp(unbind_to)
3589
3590_spentry(bind_interrupt_level_0)
3591        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3592        __(cmpl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3593        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3594        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3595        __(push rcontext(tcr.db_link))
3596        __(movl %esp,rcontext(tcr.db_link))
3597        __(movl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3598        __(js 1f)
35990:      __(jmp *%ra0)
3600        /* Interrupt level was negative; interrupt may be pending */
36011:      __(check_pending_enabled_interrupt(2f))
36022:      __(jmp *%ra0)
3603_endsubp(bind_interrupt_level_0)
3604
3605/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect  */
3606/* of disabling interrupts.)   */
3607_spentry(bind_interrupt_level_m1)
3608        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3609        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3610        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3611        __(push rcontext(tcr.db_link))
3612        __(movl %esp,rcontext(tcr.db_link))
3613        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3614        __(jmp *%ra0)
3615_endsubp(bind_interrupt_level_m1)
3616
3617/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
3618/* do what _SPbind_interrupt_level_0 does. */
3619_spentry(bind_interrupt_level)
3620        __(test %arg_z,%arg_z)
3621        __(jz _SPbind_interrupt_level_0)
3622        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3623        __(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3624        __(push $INTERRUPT_LEVEL_BINDING_INDEX)
3625        __(push rcontext(tcr.db_link))
3626        __(movl %esp,rcontext(tcr.db_link))
3627        __(movl %arg_z,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3628        __(jmp *%ra0)
3629_endsubp(bind_interrupt_level)
3630
3631/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
3632/* non-negative, check for pending interrupts. */
3633_spentry(unbind_interrupt_level)
3634        __(btl $TCR_FLAG_BIT_PENDING_SUSPEND,rcontext(tcr.flags))
3635        __(movl rcontext(tcr.tlb_pointer),%arg_y)
3636        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_y),%imm0)
3637        __(jc 5f)
36380:      __(test %imm0,%imm0)
3639        __(movl rcontext(tcr.db_link),%imm0)
3640        __(movl binding.val(%imm0),%temp0)
3641        __(movl binding.link(%imm0),%imm0)
3642        __(movl %temp0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3643        __(movl %imm0,rcontext(tcr.db_link))
3644        __(js 3f)
36452:      __(repret)
36463:      __(test %temp0,%temp0)
3647        __(js 2b)
3648        __(check_pending_enabled_interrupt(4f))
36494:      __(repret)
36505:       /* Missed a suspend request; force suspend now if we're restoring
3651          interrupt level to -1 or greater */
3652        __(cmpl $-2<<fixnumshift,%imm0)
3653        __(jne 0b)
3654        __(movl rcontext(tcr.db_link),%temp0)
3655        __(movl binding.val(%temp0),%temp0)
3656        __(cmpl %imm0,%temp0)
3657        __(je 0b)
3658        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
3659        __(suspend_now())
3660        __(jmp 0b)
3661_endsubp(unbind_interrupt_level)
3662
3663_spentry(progvrestore)
3664        __(movl rcontext(tcr.save_tsp),%imm0)
3665        __(movl tsp_frame.backlink(%imm0),%imm0) /* ignore .SPnthrowXXX values frame   */
3666        __(movl tsp_frame.data_offset(%imm0),%imm0)
3667        __(shrl $fixnumshift,%imm0)
3668        __(jne _SPunbind_n)
3669        __(repret)
3670_endsubp(progvrestore)
3671
3672/* %arg_z <- %arg_y + %arg_z.  Do the fixnum case - including overflow -  */
3673/* inline.  Call out otherwise.   */
3674_spentry(builtin_plus)
3675        __(movl %arg_y,%imm0)
3676        __(orl %arg_z,%imm0)
3677        __(testb $fixnummask,%imm0_b)
3678        __(jne 1f)
3679        __(addl %arg_y,%arg_z)
3680        __(jo C(fix_one_bit_overflow))
3681        __(repret)
36821:      __(jump_builtin(_builtin_plus,2))
3683_endsubp(builtin_plus)
3684
3685/* %arg_z <- %arg_y - %arg_z.  Do the fixnum case - including overflow -  */
3686/*  inline.  Call out otherwise.   */
3687_spentry(builtin_minus)
3688        __(movl %arg_y,%imm0)
3689        __(orl %arg_z,%imm0)
3690        __(testb $fixnummask,%imm0_b)
3691        __(jne 1f)
3692        __(xchgl %arg_y,%arg_z)
3693        __(subl %arg_y,%arg_z)
3694        __(jo C(fix_one_bit_overflow))
3695        __(repret)
36961:      __(jump_builtin(_builtin_minus,2))
3697_endsubp(builtin_minus)
3698
3699/* %arg_z -< arg_y * arg_z. */
3700/* Do the fixnum case---including overflow---inline.  Call out otherwise. */
3701_spentry(builtin_times)
3702        __(movl %arg_y,%imm0)
3703        __(orb %arg_z_b,%imm0_b)
3704        __(testb $fixnummask,%imm0_b)
3705        __(jne 2f)
3706        __(unbox_fixnum(%arg_z,%imm0))
3707        /* 32-bit fixnum result in %imm0.  Overflow set if it doesn't fit. */
3708        __(imul %arg_y,%imm0)
3709        __(jo 1f)
3710        __(movl %imm0,%arg_z)
3711        __(ret)
37121:      __(unbox_fixnum(%arg_z,%eax))
3713        __(mark_as_imm(%edx))
3714        __(unbox_fixnum(%arg_y,%edx))
3715        __(imul %edx)
3716        __(movd %eax,%mm0)
3717        __(movd %edx,%mm1)
3718        __(mark_as_node(%edx))
3719        __(psllq $32,%mm1)
3720        __(por %mm1,%mm0)
3721        __(jmp _SPmakes64)
37222:      __(jump_builtin(_builtin_times,2))
3723_endsubp(builtin_times)
3724
3725_spentry(builtin_div)
3726        __(jump_builtin(_builtin_div,2))
3727
3728/* %arg_z <- (= %arg_y %arg_z).   */
3729_spentry(builtin_eq)
3730        __(movl %arg_y,%imm0)
3731        __(orb %arg_z_b,%imm0_b)
3732        __(testb $fixnummask,%imm0_b)
3733        __(jne 1f)
3734        __(rcmpl(%arg_z,%arg_y))
3735        __(condition_to_boolean(e,%imm0,%arg_z))
3736        __(ret)
37371:      __(jump_builtin(_builtin_eq,2))
3738_endsubp(builtin_eq)
3739
3740/* %arg_z <- (/= %arg_y %arg_z).          */
3741_spentry(builtin_ne)
3742        __(movl %arg_y,%imm0)
3743        __(orb %arg_z_b,%imm0_b)
3744        __(testb $fixnummask,%imm0_b)
3745        __(jne 1f)
3746        __(rcmpl(%arg_z,%arg_y))
3747        __(condition_to_boolean(ne,%imm0,%arg_z))
3748        __(ret)
37491:      __(jump_builtin(_builtin_ne,2))
3750_endsubp(builtin_ne)
3751
3752/* %arg_z <- (> %arg_y %arg_z).   */
3753_spentry(builtin_gt)
3754        __(movl %arg_y,%imm0)
3755        __(orb %arg_z_b,%imm0_b)
3756        __(testb $fixnummask,%imm0_b)
3757        __(jne 1f)
3758        __(rcmpl(%arg_y,%arg_z))
3759        __(condition_to_boolean(g,%imm0,%arg_z))
3760        __(ret)
37611:      __(jump_builtin(_builtin_gt,2))
3762_endsubp(builtin_gt)
3763
3764/* %arg_z <- (>= %arg_y %arg_z).          */
3765_spentry(builtin_ge)
3766        __(movl %arg_y,%imm0)
3767        __(orb %arg_z_b,%imm0_b)
3768        __(testb $fixnummask,%imm0_b)
3769        __(jne 1f)
3770        __(rcmpl(%arg_y,%arg_z))
3771        __(condition_to_boolean(ge,%imm0,%arg_z))
3772        __(ret)
37731:      __(jump_builtin(_builtin_ge,2))
3774_endsubp(builtin_ge)
3775
3776/* %arg_z <- (< %arg_y %arg_z).   */
3777_spentry(builtin_lt)
3778        __(movl %arg_y,%imm0)
3779        __(orb %arg_z_b,%imm0_b)
3780        __(testb $fixnummask,%imm0_b)
3781        __(jne 1f)
3782        __(rcmpl(%arg_y,%arg_z))
3783        __(condition_to_boolean(l,%imm0,%arg_z))
3784        __(ret)
37851:      __(jump_builtin(_builtin_lt,2))
3786_endsubp(builtin_lt)
3787
3788/* %arg_z <- (<= %arg_y %arg_z).   */
3789_spentry(builtin_le)
3790        __(movl %arg_y,%imm0)
3791        __(orb %arg_z_b,%imm0_b)
3792        __(testb $fixnummask,%imm0_b)
3793        __(jne 1f)
3794        __(rcmpl(%arg_y,%arg_z))
3795        __(condition_to_boolean(le,%imm0,%arg_z))
3796        __(ret)
37971:      __(jump_builtin(_builtin_le,2))
3798_endsubp(builtin_le)
3799
3800_spentry(builtin_eql)
3801        __(cmpl %arg_y,%arg_z)
3802        __(je 1f)
3803        /* Not EQ.  Could only possibly be EQL if both are tag-misc  */
3804        /* and both have the same subtag. */
3805        __(movl %arg_y,%imm0)
3806        __(andb $tagmask,%imm0_b)
3807        __(cmpb $tag_misc,%imm0_b)
3808        __(jne 2f)
3809        __(movb %arg_z_b,%imm0_bh)
3810        __(andb $tagmask,%imm0_bh)
3811        __(cmpb %imm0_bh,%imm0_b)
3812        __(jne 2f)
3813        __(extract_subtag(%arg_y,%imm0_b))
3814        __(extract_subtag(%arg_z,%imm0_bh))
3815        __(cmpb %imm0_b,%imm0_bh)
3816        __(jne 2f)
3817        __(jump_builtin(_builtin_eql,2))
38181:      __(movl $t_value,%arg_z)
3819        __(ret)
38202:      __(movl $nil_value,%arg_z)
3821        __(ret)
3822_endsubp(builtin_eql)
3823
3824_spentry(builtin_length)
3825        __(extract_fulltag(%arg_z,%imm0))
3826        __(cmpl $tag_list,%imm0)
3827        __(jz 2f)
3828        __(andl $tagmask,%imm0)
3829        __(cmpl $tag_misc,%imm0)
3830        __(jnz 8f)
3831        __(extract_subtag(%arg_z,%imm0_b))
3832        __(rcmpb(%imm0_b,$min_vector_subtag))
3833        __(jb 8f)
3834        __(je 1f)
3835        /* (simple-array * (*)) */
3836        __(movl %arg_z,%arg_y)
3837        __(vector_length(%arg_y,%arg_z))
3838        __(ret)
38391:      /* vector header */
3840        __(movl vectorH.logsize(%arg_z),%arg_z)
3841        __(ret)
38422:      /* list.  Maybe null, maybe dotted or circular. */
3843        __(movl $-fixnumone,%arg_y)
3844        __(movl %arg_z,%temp0)  /* fast pointer */
3845        __(movl %arg_z,%temp1)  /* slow pointer */
38463:      __(movb %temp0_b,%al)
3847        __(andb $fulltagmask,%al)
3848        __(addl $fixnumone,%arg_y)
3849        __(compare_reg_to_nil(%temp0))
3850        __(je 9f)
3851        __(cmpb $fulltag_cons,%al)
3852        __(jne 8f)
3853        __(movb %temp1_b,%ah)
3854        __(andb $fulltagmask,%ah)
3855        __(_cdr(%temp0,%temp0))
3856        __(testl $fixnumone,%arg_y)
3857        __(je 3b)
3858        __(cmpb $fulltag_cons,%ah)
3859        __(jne 8f)
3860        __(_cdr(%temp1,%temp1))
3861        __(cmpl %temp0,%temp1)
3862        __(jne 3b)
38638:
3864        __(jump_builtin(_builtin_length,1))
38659:
3866        __(movl %arg_y,%arg_z)
3867        __(ret)
3868_endsubp(builtin_length)
3869
3870_spentry(builtin_seqtype)
3871        __(extract_fulltag(%arg_z,%imm0))
3872        __(cmpb $fulltag_cons,%imm0_b)
3873        __(jz 1f)
3874        __(cmpb $tag_misc,%imm0_b)
3875        __(jne 2f)
3876        __(movb misc_subtag_offset(%arg_z),%imm0_b)
3877        __(rcmpb(%imm0_b,$min_vector_subtag))
3878        __(jb 2f)
3879        __(movl $nil_value,%arg_z)
3880        __(ret)
38811:      __(movl $t_value,%arg_z)
3882        __(ret)
38832:
3884        __(jump_builtin(_builtin_seqtype,1))
3885_endsubp(builtin_seqtype)
3886
3887_spentry(builtin_assq)
3888        __(cmpl $nil_value,%arg_z)
3889        __(je 5f)
38901:      __(movl %arg_z,%imm0)
3891        __(andb $fulltagmask,%imm0_b)
3892        __(cmpb $fulltag_cons,%imm0_b)
3893        __(je 2f)
3894        __(uuo_error_reg_not_list(Rarg_z))
38952:      __(_car(%arg_z,%temp0))
3896        __(_cdr(%arg_z,%arg_z))
3897        __(cmpl $nil_value,%temp0)
3898        __(je 4f)
3899        __(movl %temp0,%imm0)
3900        __(andb $fulltagmask,%imm0_b)
3901        __(cmpb $fulltag_cons,%imm0_b)
3902        __(je 3f)
3903        __(uuo_error_reg_not_list(Rtemp0))
39043:      __(_car(%temp0,%temp1))
3905        __(cmpl %temp1,%arg_y)
3906        __(jne 4f)
3907        __(movl %temp0,%arg_z)
3908        __(ret)
39094:      __(cmpl $nil_value,%arg_z)
39105:      __(jnz 1b)
3911        __(repret)
3912_endsubp(builtin_assq)
3913
3914_spentry(builtin_memq)
3915        __(cmpl $nil_value,%arg_z)
3916        __(jmp 3f)
39171:      __(movb $fulltagmask,%imm0_b)
3918        __(andb %arg_z_b,%imm0_b)
3919        __(cmpb $fulltag_cons,%imm0_b)
3920        __(jz 2f)
3921        __(uuo_error_reg_not_list(Rarg_z))
39222:      __(_car(%arg_z,%temp1))
3923        __(_cdr(%arg_z,%temp0))
3924        __(cmpl %temp1,%arg_y)
3925        __(jz 4f)
3926        __(cmpl $nil_value,%temp0)
3927        __(movl %temp0,%arg_z)
39283:      __(jnz 1b)
39294:      __(repret)
3930_endsubp(builtin_memq)
3931
3932logbitp_max_bit = 30
3933
3934_spentry(builtin_logbitp)
3935        /* Call out unless: both args fixnums, arg_y in [0, logbitp_max_bit) */
3936        __(movl %arg_z,%imm0)
3937        __(orl %arg_y,%imm0)
3938        __(testb $fixnummask,%imm0_b)
3939        __(jnz 1f)
3940        __(unbox_fixnum(%arg_y,%imm0))
3941        __(js 1f)       /* bit number negative */
3942        __(addb $fixnumshift,%imm0_b)
3943        __(cmpl $logbitp_max_bit<<fixnumshift,%arg_y)
3944        __(jb 2f)
3945        __(movl $logbitp_max_bit-1+fixnumshift,%imm0)
39462:      __(bt %imm0,%arg_z)
3947        __(condition_to_boolean(b,%imm0,%arg_z))
3948        __(ret)
39491:      __(jump_builtin(_builtin_logbitp,2))
3950_endsubp(builtin_logbitp)
3951
3952_spentry(builtin_logior)
3953        __(movl %arg_y,%imm0)
3954        __(orb %arg_z_b,%imm0_b)
3955        __(testb $fixnummask,%imm0_b)
3956        __(jne 1f)
3957        __(orl %arg_y,%arg_z)
3958        __(ret)
39591:
3960        __(jump_builtin(_builtin_logior,2))
3961_endsubp(builtin_logior)
3962
3963_spentry(builtin_logand)
3964        __(movl %arg_y,%imm0)
3965        __(orb %arg_z_b,%imm0_b)
3966        __(testb $fixnummask,%imm0_b)
3967        __(jne 1f)
3968        __(andl %arg_y,%arg_z)
3969        __(ret)
39701:
3971        __(jump_builtin(_builtin_logand,2))
3972_endsubp(builtin_logand)
3973
3974_spentry(builtin_negate)
3975        __(testb $fixnummask,%arg_z_b)
3976        __(jne 1f)
3977        __(negl %arg_z)
3978        __(jo C(fix_one_bit_overflow))
3979        __(repret)
39801:
3981        __(jump_builtin(_builtin_negate,1))
3982_endsubp(builtin_negate)
3983
3984_spentry(builtin_logxor)
3985        __(movl %arg_y,%imm0)
3986        __(orb %arg_z_b,%imm0_b)
3987        __(testb $fixnummask,%imm0_b)
3988        __(jne 1f)
3989        __(xorl %arg_y,%arg_z)
3990        __(ret)
39911:
3992        __(jump_builtin(_builtin_logxor,2))
3993_endsubp(builtin_logxor)
3994
3995/* temp0 = vector, arg_y = index, arg_z = newval */
3996_spentry(aset1)
3997        __(extract_typecode(%temp0,%imm0))
3998        __(box_fixnum(%imm0,%temp1))
3999        __(cmpb $min_vector_subtag,%imm0_b)
4000        __(ja _SPsubtag_misc_set)
4001        /* push frame... */
4002        __(pop %temp1)
4003        __(push $reserved_frame_marker)
4004        __(push $reserved_frame_marker)
4005        __(push %temp0)
4006        __(push %temp1)
4007        /* and fall through... */
4008_endsubp(aset1)
4009
4010_spentry(builtin_aset1)
4011        __(jump_builtin(_builtin_aset1,3))
4012_endsubp(builtin_aset1)
4013
4014_spentry(builtin_ash)
4015        __(movl %arg_y,%imm0)
4016        __(orb %arg_z_b,%imm0_b)
4017        __(testb $fixnummask,%imm0_b)
4018        __(jne 9f)
4019        __(unbox_fixnum(%arg_z,%imm0))
4020        /* Z flag set if zero ASH shift count */
4021        __(jnz 1f)
4022        __(movl %arg_y,%arg_z) /* shift by 0 */
4023        __(ret)
40241:      __(jns 3f)
4025        __(rcmpl(%imm0,$-31))
4026        __(jg 2f)
4027        __(unbox_fixnum(%arg_y,%imm0))
4028        __(sar $31,%imm0)
4029        __(box_fixnum(%imm0,%arg_z))
4030        __(ret)
40312:      /* Right-shift by small fixnum */
4032        __(negb %imm0_b)
4033        __(movzbl %imm0_b,%ecx)
4034        __(unbox_fixnum(%arg_y,%imm0))
4035        __(sar %cl,%imm0)
4036        __(box_fixnum(%imm0,%arg_z))
4037        __(ret)
40383:      /* Left shift by fixnum.  We can't shift by more than 31 bits, */
4039        /* though shifting by 32 is actually easy. */
4040        __(rcmpl(%imm0,$32))
4041        __(jg 9f)
4042        __(jne 4f)
4043        /* left-shift by 32 bits exactly */
4044        __(unbox_fixnum(%arg_y,%imm0))
4045        __(movd %imm0,%mm0)
4046        __(psllq $32,%mm0)
4047        __(jmp _SPmakes64)
40484:      /* left-shift by 1..31 bits. Safe to move shift count to %cl */
4049        __(movd %imm0,%mm1)     /* shift count */
4050        __(unbox_fixnum(%arg_y,%imm0))
4051        __(movd %imm0,%mm0)
4052        __(sarl $31,%imm0)      /* propagate sign */
4053        __(movd %imm0,%mm2)
4054        __(pshufw $0x4e,%mm2,%mm2) /* swap hi/lo halves */
4055        __(por %mm2,%mm0)
4056        __(psllq %mm1,%mm0)
4057        __(jmp _SPmakes64)
40589:
4059        __(jump_builtin(_builtin_ash,2))
4060_endsubp(builtin_ash)
4061
4062_spentry(builtin_aref1)
4063        __(extract_typecode(%arg_y,%imm0))
4064        __(box_fixnum_no_flags(%imm0,%temp0))
4065        __(cmpb $min_vector_subtag,%imm0_b)
4066        __(ja _SPsubtag_misc_ref)
4067        __(jump_builtin(_builtin_aref1,2))
4068_endsubp(builtin_aref1)
4069
4070/* Maybe check the x87 tag word to see if st(0) is valid and pop it */
4071/* if so.  This might allow us to avoid having to have a priori */
4072/* knowledge of whether a foreign function returns a floating-point result. */
4073/* backlink to saved %esp, below */
4074/* arg n-1 */
4075/* arg n-2 */
4076/* ... */
4077/* arg 0 */
4078/* space for alignment */
4079/* previous %esp */
4080
4081_spentry(ffcall)
4082LocalLabelPrefix[]ffcall:
4083        __(unbox_fixnum(%arg_z,%imm0))
4084        __(testb $fixnummask,%arg_z_b)
4085        __(je 0f)
4086        __(movl macptr.address(%arg_z),%imm0)
40870:
4088        /* Save lisp registers. */
4089        __(push %ebp)
4090        __(mov %esp,%ebp)
4091        __(push %temp0)                 
4092        __(push %temp1)                 
4093        __(push %arg_y)                 
4094        __(push %arg_z)                 
4095        __(push %fn)         
4096        __ifdef([WIN32_ES_HACK])
4097         __(movl rcontext(tcr.linear),%ebx)
4098        __endif
4099        __(movl %esp,rcontext(tcr.save_vsp))
4100        __(movl %ebp,rcontext(tcr.save_ebp))
4101        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4102        __(movl rcontext(tcr.foreign_sp),%esp)
4103        /* preserve state of direction flag */
4104        __(pushfl)
4105        __(popl rcontext(tcr.save_eflags))
4106        __(cld)       
4107        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4108        __(emms)
4109        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4110        __(movl (%esp),%ebp)
4111LocalLabelPrefix[]ffcall_setup:
4112        __(lea 15(%esp),%ecx)
4113        __(andl $-16,%ecx)
4114        __(movl %ecx,%esp)
4115/*      __(addl $node_size,%esp) */
4116        __ifdef([WIN32_ES_HACK])
4117         __(push %ds)
4118         __(pop %es)
4119        __endif
4120LocalLabelPrefix[]ffcall_call:
4121        __(call *%eax)
4122        __ifdef([WIN32_ES_HACK])
4123         __(movw tcr.ldt_selector(%ebx),%rcontext_reg)
4124        __endif
4125LocalLabelPrefix[]ffcall_call_end:
4126        __(movl %ebp,%esp)
4127        __(movl %esp,rcontext(tcr.foreign_sp))
4128        /* The high word of a 64-bit result would be in %edx right now.
4129           There doesn't seem to be any other good place to put this,
4130           though %edx is often undefined at this point. */
4131        __(mov %edx,rcontext(tcr.unboxed1))
4132        __(clr %arg_z)
4133        __(clr %arg_y)
4134        __(clr %temp1)
4135        __(clr %temp0)
4136        __(clr %fn)
4137        __(pxor %fpzero,%fpzero)
4138        __(cmpb $0,C(bogus_fp_exceptions))
4139        __(je 0f)
4140        __(movl %arg_z,rcontext(tcr.ffi_exception))
4141        __(jmp 1f)
41420:      __(stmxcsr rcontext(tcr.ffi_exception))
41431:      __(pushl rcontext(tcr.save_eflags))
4144        __(popfl)
4145        __(movl rcontext(tcr.save_vsp),%esp)
4146        __(movl rcontext(tcr.save_ebp),%ebp)
4147        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4148        __(pop %fn)             
4149        __(pop %arg_z)           
4150        __(pop %arg_y)           
4151        __(pop %temp1)
4152        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4153        __(check_pending_interrupt(%temp0))
4154        __(pop %temp0)
4155        __(leave)
4156        __(ret)
4157        /* need to deal with NSExceptions and Objc-2.0 execptions */
4158_endsubp(ffcall)
4159
4160_spentry(ffcall_return_registers)
4161        __(int $3)
4162_endsubp(ffcall_return_registers)
4163
4164/* We need to reserve a frame here if (a) nothing else was already pushed
4165/* and (b) we push something (e.g., more than 2 args in the lexpr) */
4166_spentry(spread_lexprz)
4167        new_local_labels()
4168        __(movl (%arg_z),%imm0) /* lexpr count */
4169        __(leal node_size(%arg_z,%imm0),%arg_y)
4170        __(movd %arg_y,%mm1)
4171        __(test %nargs,%nargs) /* anything pushed by caller ? */
4172        __(jne 0f)              /* yes, caller has already created frame. */
4173        __(cmpl $(nargregs*node_size),%imm0) /* will we push anything ? */
4174        __(jbe 0f)
4175        __(push $reserved_frame_marker)
4176        __(push $reserved_frame_marker)
41770:      __(addl %imm0,%nargs)
4178        __(cmpl $(1*node_size),%imm0)
4179        __(ja 2f)
4180        __(je 1f)
4181        /* lexpr count was 0; vpop the args that */
4182        /* were pushed by the caller */
4183        __(test %nargs,%nargs)
4184        __(je local_label(all_args_popped))
4185        __(pop %arg_z)
4186local_label(maybe_pop_y):
4187        __(cmpl $(1*node_size),%nargs)
4188        __(je local_label(all_args_popped))
4189        __(pop %arg_y)
4190local_label(all_args_popped):   
4191        /* If all args fit in registers but some were pushed */
4192        /* by the caller, discard the reserved frame that the caller */
4193        /* pushed.         */
4194        __(cmpl %imm0,%nargs)
4195        __(je local_label(go))
4196        __(cmpl $(nargregs*node_size),%nargs)
4197        __(ja local_label(go))
4198        __(addl $(2*node_size),%esp)
4199local_label(go):
4200        __(jmp *%ra0)
4201
4202        /* lexpr count is two or more: vpush args from the lexpr until */
4203        /* we have only two left, then assign them to arg_y and arg_z */
42042:      __(cmpl $(2*node_size),%imm0)
4205        __(je local_label(push_loop_end))
4206local_label(push_loop):
4207        __(lea -1*node_size(%imm0),%imm0)
4208        __(push -node_size(%arg_y))
4209        __(lea -1*node_size(%arg_y),%arg_y)
4210        __(cmpl $(2*node_size),%imm0)
4211        __(jne 2b)
4212local_label(push_loop_end):
4213        __(movl -node_size*2(%arg_y),%arg_z)
4214        __(movl -node_size*1(%arg_y),%arg_y)
4215        __(jmp *%ra0)
4216        /* lexpr count is one: set arg_z from the lexpr, */
4217        /* maybe vpop arg_y  */
42181:      __(movl -node_size*1(%arg_y),%arg_z)
4219        __(jmp local_label(maybe_pop_y))
4220_endsubp(spread_lexprz)
4221
4222_spentry(callback)
4223        __(push %ebp)
4224        __(movl %esp,%ebp)
4225        /* C scalar args are already on the stack. */
4226        /* arg word 0 at 8(%ebp), word 1 at 12(%ebp), etc. */
4227
4228        /* Reserve some space for results, relative to the
4229           current %ebp.  We may need quite a bit of it. */
4230        __(subl $24,%esp)
4231        __(movl $0,-16(%ebp)) /* No FP result */
4232        __(movl %eax,%ecx)    /* extract args-discard count */
4233        __(shrl $24,%ecx)
4234        __(andl $0x00ffffff,%eax)
4235        __(movl %ecx,-12(%ebp))
4236        /* If the C stack is 16-byte aligned by convention,
4237           it should still be, and this'll be a NOP. */
4238        __(andl $~15,%esp)
4239        /* C NVRs */
4240        __(push %edi)
4241        __(push %esi)
4242        __(push %ebx)
4243        __(push %ebp)
4244        __(box_fixnum(%eax,%esi))       /* put callback index in arg_y */
4245        __(ref_global(get_tcr,%eax))
4246        __(push $1)
4247        __(call *%eax)
4248        __(addl $node_size,%esp)
4249        /* linear TCR addr now in %eax */
4250        __(movw tcr.ldt_selector(%eax), %rcontext_reg)
4251
4252        /* ebp is 16-byte aligned, and we've pushed 4 words.  Make
4253          sure that when we push old foreign_sp, %esp will be 16-byte
4254          aligned again */
4255        __(subl $8,%esp)
4256        __(pushl rcontext(tcr.save_ebp))  /* mark cstack frame's "owner" */
4257        __(push rcontext(tcr.foreign_sp))
4258        __(movl %esp,rcontext(tcr.foreign_sp))
4259        __(clr %arg_z)
4260        /* arg_y contains callback index */
4261        __(clr %temp1)
4262        __(clr %temp0)
4263        __(clr %fn)
4264        __(pxor %fpzero,%fpzero)
4265        __(movl rcontext(tcr.save_vsp),%esp)
4266        __(movl %ebp,%arg_z)
4267        __(movl rcontext(tcr.save_ebp),%ebp)
4268        __(movl $TCR_STATE_LISP,rcontext(tcr.valence))
4269        __(stmxcsr rcontext(tcr.foreign_mxcsr))
4270        __(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
4271        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
4272        __(movl $nrs.callbacks,%fname)
4273        __(check_cstack_alignment())
4274        __(push $local_label(back_from_callback))
4275        __(set_nargs(2))
4276        __(jump_fname())
4277__(tra(local_label(back_from_callback)))
4278        __(movl %esp,rcontext(tcr.save_vsp))
4279        __(movl %ebp,rcontext(tcr.save_ebp))
4280        __(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
4281        __(movl rcontext(tcr.foreign_sp),%esp)
4282        __(stmxcsr rcontext(tcr.lisp_mxcsr))
4283        __(emms)
4284        __(pop rcontext(tcr.foreign_sp))
4285        __(addl $12,%esp)       /* discard alignment padding */
4286        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
4287        __ifdef([WIN32_ES_HACK])
4288         __(push %ds)
4289         __(pop %es)
4290        __endif
4291        __(pop %ebp)
4292        __(pop %ebx)
4293        __(pop %esi)
4294        __(pop %edi)
4295        __(cmpb $1,-16(%ebp))
4296        __(movl -12(%ebp),%ecx) /* magic value for ObjC bridge or winapi */
4297        __(jae 1f)
4298        __(movl -8(%ebp),%eax)
4299        __(movl -4(%ebp),%edx)
4300        __(leave)
4301        __ifdef([WIN_32])
4302         __(testl %ecx,%ecx)
4303         __(jne local_label(winapi_return))
4304         __(repret)
4305        __else
4306         __(ret)
4307        __endif
43081:      __(jne 2f)
4309        /* single float return in x87 */
4310        __(flds -8(%ebp))
4311        __(leave)
4312        __ifdef([WIN_32])
4313         __(testl %ecx,%ecx)
4314         __(jne local_label(winapi_return))
4315         __(repret)
4316        __else
4317         __(ret)
4318        __endif
43192:      /* double-float return in x87 */
4320        __(fldl -8(%ebp))
4321        __(leave)
4322        __ifdef([WIN_32])
4323         __(testl %ecx,%ecx)
4324         __(jne local_label(winapi_return))
4325         __(repret)
4326        __else
4327         __(ret)
4328        __endif
4329        __ifdef([WIN_32])
4330local_label(winapi_return):             
4331         /* %ecx is non-zero and contains count of arg words to pop */
4332          __(popl (%esp,%ecx,4))
4333          __(leal -4(%esp,%ecx,4),%esp)
4334          __(ret)
4335        __endif
4336_endsubp(callback)
4337
4338/* temp0 = array, arg_y = i, arg_z = j. Typecheck everything.
4339   We don't know whether the array is alleged to be simple or
4340   not, and don't know anythng about the element type.  */
4341
4342_spentry(aref2)
4343        __(testl $fixnummask,%arg_y)
4344        __(je 0f)
4345        __(uuo_error_reg_not_fixnum(Rarg_y))
43460:      __(testb $fixnummask,%arg_z_b)
4347        __(je 1f)
4348        __(uuo_error_reg_not_fixnum(Rarg_z))
43491:      __(extract_typecode(%temp0,%imm0))
4350        __(cmpb $subtag_arrayH,%imm0_b)
4351        __(jne 2f)
4352        __(cmpl $2<<fixnumshift,arrayH.rank(%temp0))
4353        __(je 3f)
43542:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_2d))
43553:      __(cmpl arrayH.dim0(%temp0),%arg_y)
4356        __(jb 4f)
4357        __(uuo_error_array_bounds(Rarg_y,Rtemp0))
43584:      __(movl arrayH.dim0+node_size(%temp0),%imm0)
4359        __(cmpl %imm0,%arg_z)
4360        __(jb 5f)
4361        __(uuo_error_array_bounds(Rarg_z,Rtemp0))
43625:      __(sarl $fixnumshift,%imm0)
4363        __(imull %arg_y,%imm0)
4364        __(addl %imm0,%arg_z)
4365        __(movl %temp0,%arg_y)
4366        __(xorl %temp1,%temp1)
43676:      __(addl arrayH.displacement(%arg_y),%arg_z)
4368        __(movl arrayH.data_vector(%arg_y),%arg_y)
4369        __(extract_subtag(%arg_y,%imm0_b))
4370        __(cmpb $subtag_vectorH,%imm0_b)
4371        __(ja C(misc_ref_common))
4372        __(jmp 6b)
4373_endsubp(aref2)
4374
4375/* Like aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = k */
4376_spentry(aref3)
4377        __(testb $fixnummask,%temp0_b)
4378        __(jne 0f)
4379        __(testl $fixnummask,%arg_y)
4380        __(jne 1f)
4381        __(testb $fixnummask,%arg_z_b)
4382        __(jne 2f)
4383        __(extract_typecode(%temp1,%imm0))
4384        __(cmpb $subtag_arrayH,%imm0_b)
4385        __(jne 3f)
4386        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4387        __(jne 3f)
4388        __(cmpl arrayH.dim0(%temp1),%temp0)
4389        __(jae 4f)
4390        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4391        __(cmpl %imm0,%arg_y)
4392        __(jae 5f)
4393        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_z)
4394        __(jae 6f)
4395        /* index computation: k + dim2 * (j + dim1 * i) */
4396        /* (plus minor fussing for fixnum scaling) */
4397        __(sarl $fixnumshift,%imm0)
4398        __(imull %imm0,%temp0)
4399        __(addl %arg_y,%temp0)
4400        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4401        __(sarl $fixnumshift,%imm0)
4402        __(imull %imm0,%temp0)
4403        __(addl %temp0,%arg_z)
4404        __(movl %temp1,%arg_y)
44058:      __(addl arrayH.displacement(%arg_y),%arg_z)
4406        __(movl arrayH.data_vector(%arg_y),%arg_y)
4407        __(extract_subtag(%arg_y,%imm0_b))
4408        __(cmpb $subtag_vectorH,%imm0_b)
4409        __(ja C(misc_ref_common))
4410        __(jmp 8b)
44110:      __(uuo_error_reg_not_fixnum(Rtemp0))
44121:      __(uuo_error_reg_not_fixnum(Rarg_y))
44132:      __(uuo_error_reg_not_fixnum(Rarg_z))
44143:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
44154:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
44165:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
44176:      __(uuo_error_array_bounds(Rarg_z,Rtemp1))
4418_endsubp(aref3)
4419
4420/* As with aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = new_value */
4421_spentry(aset2)
4422        __(testb $fixnummask,%temp0_b)
4423        __(je 0f)
4424        __(uuo_error_reg_not_fixnum(Rtemp0))
44250:      __(testl $fixnummask,%arg_y)
4426        __(je 1f)
4427        __(uuo_error_reg_not_fixnum(Rarg_y))
44281:      __(extract_typecode(%temp1,%imm0))
4429        __(cmpb $subtag_arrayH,%imm0_b)
4430        __(jne 2f)
4431        __(cmpl $2<<fixnumshift,arrayH.rank(%temp1))
4432        __(je 3f)
44332:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_2d))
44343:      __(cmpl arrayH.dim0(%temp1),%temp0)
4435        __(jb 4f)
4436        __(uuo_error_array_bounds(Rtemp0,Rtemp1))
44374:      __(movl arrayH.dim0+node_size(%temp1),%imm0)
4438        __(cmpl %imm0,%arg_y)
4439        __(jb 5f)
4440        __(uuo_error_array_bounds(Rarg_y,Rtemp1))
44415:      __(sarl $fixnumshift,%imm0)
4442        __(imull %temp0,%imm0)
4443        __(addl %imm0,%arg_y)
4444        __(movl %temp1,%temp0)
4445        __(xorl %temp1,%temp1)
44466:      __(addl arrayH.displacement(%temp0),%arg_y)
4447        __(movl arrayH.data_vector(%temp0),%temp0)
4448        __(extract_subtag(%temp0,%imm0_b))
4449        __(cmpb $subtag_vectorH,%imm0_b)
4450        __(ja C(misc_set_common))
4451        __(jmp 6b)
4452_endsubp(aset2)
4453
4454/* temp1 = array, imm0 = i, temp0 = j, arg_y = k, arg_z = newval */
4455/* ARRAY-DIMENSION-LIMIT is required to be a fixnum, so using imm0 is OK. */
4456_spentry(aset3)
4457        __(testb $fixnummask,%imm0_b)
4458        __(jne 0f)
4459        __(push %imm0)
4460        __(testb $fixnummask,%temp0_b)
4461        __(jne 1f)
4462        __(testl $fixnummask,%arg_y)
4463        __(jne 2f)
4464        __(extract_typecode(%temp1,%imm0))
4465        __(cmpb $subtag_arrayH,%imm0_b)
4466        __(jne 3f)
4467        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4468        __(jne 3f)
4469        __(movl arrayH.dim0(%temp1),%imm0)
4470        __(cmpl %imm0,(%esp))   /* i on stack */
4471        __(jae 4f)
4472        __(movl arrayH.dim0+node_size(%temp1),%imm0)
4473        __(cmpl %imm0,%temp0)
4474        __(jae 5f)
4475        __(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_y)
4476        __(jae 6f)
4477        /* index computation: k + dim2 * (j + dim1 * i) */
4478        /* (plus minor fussing for fixnum scaling) */
4479        __(sarl $fixnumshift,%imm0)
4480        __(imull (%esp),%imm0)  /* i on stack */
4481        __(addl %imm0,%temp0)
4482        __(addl $node_size,%esp)
4483        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
4484        __(sarl $fixnumshift,%imm0)
4485        __(imull %imm0,%temp0)
4486        __(addl %temp0,%arg_y)
4487        __(movl %temp1,%temp0)
44888:      __(addl arrayH.displacement(%temp0),%arg_y)
4489        __(movl arrayH.data_vector(%temp0),%temp0)
4490        __(extract_subtag(%temp0,%imm0_b))
4491        __(cmpb $subtag_vectorH,%imm0_b)
4492        __(ja C(misc_set_common))
4493        __(jmp 8b)
44940:      __(uuo_error_reg_not_fixnum(Rimm0))
44951:      __(uuo_error_reg_not_fixnum(Rtemp0))
44962:      __(uuo_error_reg_not_fixnum(Rarg_y))
44973:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_3d))
44984:      __(uuo_error_array_bounds(Rimm0,Rtemp1))
44995:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
45006:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
4501_endsubp(aset3)
4502
4503/* Prepend all but the first seven (6 words of code & other immediate data,
4504/* plus inner fn) and last (lfbits) elements of %fn to the "arglist". */
4505_spentry(call_closure)
4506        new_local_labels()
4507        __(vector_length(%fn,%imm0))
4508        __(subl $8<<fixnumshift,%imm0)  /* imm0 = inherited arg count */
4509        __(lea (%nargs,%imm0),%temp0)
4510        __(cmpl $nargregs<<fixnumshift,%temp0)
4511        __(jna local_label(regs_only))  /* either: 1 arg, 1 inherited, or */
4512                                        /* no args, 2 inherited */
4513        __(pop rcontext(tcr.save0))             /* save return address */
4514        __(cmpl $nargregs<<fixnumshift,%nargs)
4515        __(jna local_label(no_insert))
4516
4517/* Some arguments have already been pushed.  Push %imm0's worth */
4518/* of NILs, copy those arguments that have already been vpushed from */
4519/* the old TOS to the new, then insert all of the inherited args */
4520/* and go to the function. */
4521
4522        __(mov %imm0,%temp0)
4523local_label(push_nil_loop):
4524        __(push $nil_value)
4525        __(sub $fixnumone,%temp0)
4526        __(jne local_label(push_nil_loop))
4527
4528/* Need to use arg regs as temporaries.  Stash them in the spill area. */
4529        __(movl %arg_y,rcontext(tcr.save1))
4530        __(movl %arg_z,rcontext(tcr.save2))
4531
4532        __(leal (%esp,%imm0),%temp0)    /* start of already-pushed args */
4533        __(leal -nargregs<<fixnumshift(%nargs),%arg_y) /* args pushed */
4534        __(movd %imm0,%mm0)     /* save inherited arg count */
4535        __(xorl %imm0,%imm0)
4536local_label(copy_already_loop):
4537        __(movl (%temp0,%imm0),%arg_z)
4538        __(movl %arg_z,(%esp,%imm0))
4539        __(addl $fixnumone,%imm0)
4540        __(cmpl %imm0,%arg_y)
4541        __(jne local_label(copy_already_loop))
4542
4543        __(lea -node_size(%temp0,%imm0),%arg_y) /* start of args on stack */
4544        __(movl $7<<fixnumshift,%temp0) /* skip code, new fn */
4545        __(movd %mm0,%imm0)
4546local_label(insert_loop):
4547        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4548        __(addl $node_size,%temp0)
4549        __(addl $fixnumone,%nargs)
4550        __(movl %arg_z,(%arg_y))
4551        __(subl $node_size,%arg_y)
4552        __(subl $fixnumone,%imm0)
4553        __(jne local_label(insert_loop))
4554
4555        /* Recover arg regs, saved earlier */
4556        __(movl rcontext(tcr.save1),%arg_y)
4557        __(movl rcontext(tcr.save2),%arg_z)
4558        __(jmp local_label(go))
4559       
4560/* Here if no args were pushed by the caller. */
4561/* cases: */
4562/* no args, more than two inherited args */
4563/* a single arg in arg_z, more than one inherited arg */
4564/* two args in arg_y and arg_z, some number of inherited args */
4565
4566/* Therefore, we're always going to have to push something (the sum of */
4567/* %nargs and %imm0 will always be greater than $nargregs), and */
4568/* we will have to reserve space for a stack frame. */
4569/* The 0 args, 2 inherited case and the 1 arg, 1 inherited case get */
4570/* handled at local_label(regs_ony). */
4571       
4572local_label(no_insert):
4573        /* Reserve space for a stack frame */
4574        __(push $reserved_frame_marker)
4575        __(push $reserved_frame_marker)
4576        __(lea 7<<fixnumshift(%imm0),%temp0)    /* last inherited arg */
4577        __(rcmpl(%nargs,$fixnumone))
4578        __(je local_label(set_arg_y))
4579        __(jb local_label(set_y_z))
4580        /* %nargs = $nargregs (i.e., 2), vpush remaining inherited vars. */
4581
4582local_label(vpush_remaining):
4583        __(movl $7<<fixnumshift,%temp0)
4584local_label(vpush_remaining_loop):
4585        __(push misc_data_offset(%fn,%temp0))
4586        __(add $node_size,%temp0)
4587        __(add $fixnumone,%nargs)
4588        __(sub $node_size,%imm0)
4589        __(jnz local_label(vpush_remaining_loop))
4590        __(jmp local_label(go))
4591       
4592local_label(set_arg_y):
4593        /* one arg in arg_z.  set arg_y and vpush remaining inherited args */
4594        __(subl $node_size,%temp0)
4595        __(movl misc_data_offset(%fn,%temp0),%arg_y)
4596        __(addl $fixnumone,%nargs)
4597        __(subl $fixnumone,%imm0)
4598        __(jmp local_label(vpush_remaining))
4599local_label(set_y_z):
4600        __(subl $node_size,%temp0)
4601        __(movl misc_data_offset(%fn,%temp0),%arg_z)
4602        __(addl $fixnumone,%nargs)
4603        __(subl $fixnumone,%imm0)
4604        __(jmp local_label(set_arg_y))
4605
4606local_label(go):
4607        __(movl misc_data_offset+(6*node_size)(%fn),%fn)
4608        __(push rcontext(tcr.save0))    /* restore return addr */
4609        __(movapd %fpzero,rcontext(tcr.save0))  /* clear out spill area */
4610        __(jmp *%fn)
4611local_label(regs_only):
4612        __(lea 7<<fixnumshift(%imm0),%temp0)
4613        __(test %nargs,%nargs)
4614        __(jne local_label(one_arg))
4615        /* no args passed, two inherited args */
4616        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_z)
4617        __(cmpl $node_size,%imm0)
4618        __(je local_label(rgo))
4619        __(movl misc_data_offset-(node_size*2)(%fn,%temp0),%arg_y)
4620local_label(rgo):
4621        __(addl %imm0,%nargs)
4622        __(jmp *misc_data_offset+(6*node_size)(%fn))
4623local_label(one_arg):
4624        /* one arg was passed, so there's one inherited arg */
4625        __(movl misc_data_offset-node_size(%fn,%temp0),%arg_y)
4626        __(jmp local_label(rgo))
4627_endsubp(call_closure)
4628
4629_spentry(poweropen_callbackX)
4630        __(int $3)
4631_endsubp(poweropen_callbackX)
4632
4633_spentry(poweropen_ffcallX)
4634        __(int $3)
4635_endsubp(poweropen_ffcallX)
4636
4637_spentry(eabi_ff_call)
4638        __(int $3)
4639_endsubp(eabi_ff_call)
4640
4641_spentry(eabi_callback)
4642        __(int $3)
4643_endsubp(eabi_callback)
4644
4645
4646/* Unused, and often not used on PPC either  */
4647_spentry(callbuiltin)
4648        __(int $3)
4649_endsubp(callbuiltin)
4650
4651_spentry(callbuiltin0)
4652        __(int $3)
4653_endsubp(callbuiltin0)
4654
4655_spentry(callbuiltin1)
4656        __(int $3)
4657_endsubp(callbuiltin1)
4658
4659_spentry(callbuiltin2)
4660        __(int $3)
4661_endsubp(callbuiltin2)
4662
4663_spentry(callbuiltin3)
4664        __(int $3)
4665_endsubp(callbuiltin3)
4666
4667_spentry(restorefullcontext)
4668        __(int $3)
4669_endsubp(restorefullcontext)
4670
4671_spentry(savecontextvsp)
4672        __(int $3)
4673_endsubp(savecontextvsp)
4674
4675_spentry(savecontext0)
4676        __(int $3)
4677_endsubp(savecontext0)
4678
4679_spentry(restorecontext)
4680        __(int $3)
4681_endsubp(restorecontext)
4682
4683_spentry(stkconsyz)
4684        __(int $3)
4685_endsubp(stkconsyz)
4686
4687_spentry(stkvcell0)
4688        __(int $3)
4689_endsubp(stkvcell0)
4690
4691_spentry(stkvcellvsp)
4692        __(int $3)
4693_endsubp(stkvcellvsp)
4694
4695_spentry(breakpoint)
4696        __(int $3)
4697_endsubp(breakpoint)
4698
4699
4700/* %temp1 = array, %temp0 = i,%arg_y = j, %arg_z = k */
4701/*
4702_spentry(aref3)
4703        __(testb $fixnummask,%temp0_b)
4704        __(je 0f)
4705        __(uuo_error_reg_not_fixnum(Rtemp0))
47060:      __(testl $fixnummask,%arg_y)
4707        __(je 1f)
4708        __(uuo_error_reg_not_fixnum(Rarg_y))
47091:      __(testb $fixnummask,%arg_z_b)
4710        __(je 2f)
4711        __(uuo_error_reg_not_fixnum(Rarg_z))
47122:      __(extract_typecode(%temp1,%imm0))
4713        __(cmpb $subtag_arrayH,%imm0_b)
4714        __(jne 3f)
4715        __(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
4716        __(je 4f)
47173:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
47184:      __(cmpl arrayH.dim0(%temp1),%temp0)
4719        __(jb 5f)
4720        __(uuo_error_array_bounds(Rtemp0,Rtemp1))
47215:      __(movl arrayH.dim0+node_size(%temp1),%imm0)
4722        __(cmpl %imm0,%arg_y)
4723        __(jb 6f)
4724        __(uuo_error_array_bounds(Rarg_y,Rtemp1))
47256:      __(unbox_fixnum(%imm0,%imm0))
4726        __(movl arrayH.dim0+(node_size*2)(%temp1),%imm1)
4727        __(cmpq %imm1,%arg_z)
4728        __(jb 7f)
4729        __(uuo_error_array_bounds(Rarg_z,Rtemp0))
47307:      __(unbox_fixnum(%imm1,%imm1))
4731        __(imulq %imm1,%arg_y)
4732        __(mulq %imm1)
4733        __(imulq %imm0,%arg_x)
4734        __(addq %arg_x,%arg_z)
4735        __(addq %arg_y,%arg_z)
4736        __(movq %temp0,%arg_y)
47378:      __(addq arrayH.displacement(%arg_y),%arg_z)
4738        __(movq arrayH.data_vector(%arg_y),%arg_y)
4739        __(extract_subtag(%arg_y,%imm1_b))
4740        __(cmpb $subtag_vectorH,%imm1_b)
4741        __(ja C(misc_ref_common))
4742        __(jmp 8b)
4743_endsubp(aref3)
4744*/       
4745
4746/* %temp1 = array, %imm0 = i, %temp0 = j, %arg_y = k, %arg_z = newval. */
4747/*
4748_spentry(aset3)
4749        __(testb $fixnummask,%temp0_b)
4750        __(je 0f)
4751        __(uuo_error_reg_not_fixnum(Rtemp0))
47520:      __(testb $fixnummask,%arg_x_b)
4753        __(je 1f)
4754        __(uuo_error_reg_not_fixnum(Rarg_x))
47551:      __(testb $fixnummask,%arg_y_b)
4756        __(je 2f)
4757        __(uuo_error_reg_not_fixnum(Rarg_y))
47582:      __(extract_typecode(%temp1,%imm0))
4759        __(cmpb $subtag_arrayH,%imm0_b)
4760        __(jne 3f)
4761        __(cmpq $3<<fixnumshift,arrayH.rank(%temp1))
4762        __(je 4f)
47633:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
47644:      __(cmpq arrayH.dim0(%temp1),%temp0)
4765        __(jb 5f)
4766        __(uuo_error_array_bounds(Rtemp0,Rtemp1))
47675:      __(movq arrayH.dim0+node_size(%temp1),%imm0)
4768        __(cmpq %imm0,%arg_x)
4769        __(jb 6f)
4770        __(uuo_error_array_bounds(Rarg_x,Rtemp1))
47716:      __(unbox_fixnum(%imm0,%imm0))
4772        __(movq arrayH.dim0+(node_size*2)(%temp1),%imm1)
4773        __(cmpq %imm1,%arg_y)
4774        __(jb 7f)
4775        __(uuo_error_array_bounds(Rarg_y,Rtemp1))
47767:      __(unbox_fixnum(%imm1,%imm1))
4777        __(imulq %imm1,%arg_x)
4778        __(mulq %imm1)
4779        __(imulq %imm0,%temp0)
4780        __(addq %temp0,%arg_y)
4781        __(addq %arg_x,%arg_y)
4782        __(movq %temp1,%arg_x)
47838:      __(addq arrayH.displacement(%arg_x),%arg_y)
4784        __(movq arrayH.data_vector(%arg_x),%arg_x)
4785        __(extract_subtag(%arg_x,%imm1_b))
4786        __(cmpb $subtag_vectorH,%imm1_b)
4787        __(ja C(misc_set_common))
4788        __(jmp 8b)
4789_endsubp(aset3)
4790*/
4791
4792_spentry(unused_6)
4793        __(int $3)
4794Xspentry_end:
4795_endsubp(unused_6)
4796        .data
4797        .globl C(spentry_start)
4798        .globl C(spentry_end)
4799C(spentry_start):       .long Xspentry_start
4800C(spentry_end):         .long Xspentry_end
4801       
Note: See TracBrowser for help on using the repository browser.