source: release/1.9/source/lisp-kernel/x86-spentry32.s @ 16083

Last change on this file since 16083 was 16004, checked in by rme, 5 years ago

Merge a couple of bug fixes from trunk.

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