source: branches/arm/lisp-kernel/arm-spentry.s @ 13811

Last change on this file since 13811 was 13811, checked in by gb, 9 years ago

In _SPvalues: push1 macro operands backwards.
In _SPgvset: memoize like _SPrplaca/_SPrplacd and other things do.

File size: 143.1 KB
Line 
1/* Copyright (C) 2010 Clozure Associates */
2/* This file is part of Clozure CL.   */
3
4/* Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
5/* License , known as the LLGPL and distributed with Clozure CL as the */
6/* file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
7/* which is distributed with Clozure CL as the file "LGPL".  Where these */
8/* conflict, the preamble takes precedence.   */
9
10/* Clozure CL is referenced in the preamble as the "LIBRARY." */
11
12/* The LLGPL is also available online at */
13/* http://opensource.franz.com/preamble.html */
14
15
16
17        include(lisp.s)
18        _beginfile
19        .align 2
20        .arm
21        .syntax unified
22
23local_label(start):
24        .set delta,256
25        .set spnum,0
26        .set sporg,0
27define(`_spentry',`ifdef(`__func_name',`_endfn',`')
28        .org sporg
29        .set sporg,sporg+delta
30        .set spnum,spnum+1
31        .if spnum >= 112
32        .set delta,1024
33        .endif
34        _exportfn(_SP$1)
35        .line  __line__
36')
37
38
39define(`_endsubp',`
40        _endfn(_SP$1)
41# __line__
42')
43
44
45       
46
47define(`jump_builtin',`
48        ref_nrs_value(fname,builtin_functions)
49        set_nargs($2)
50        vrefr(fname,fname,$1)
51        jump_fname()
52')
53
54/* Set the _function.entrypoint locative in nfn - which pointed here -
55   to the address of the first instruction in the _function.codevector.
56   This must be the first ARM subprim. */
57
58_spentry(fix_nfn_entrypoint)
59        __(build_lisp_frame(imm0))
60        __(vpush1(arg_z))
61        __(ldr arg_z,[nfn,#_function.codevector])
62        __(add lr,arg_z,#misc_data_offset)
63        __(str lr,[nfn,#_function.entrypoint])
64        __(vpop1(arg_z))
65        __(restore_lisp_frame(imm0))
66        __(jump_nfn())
67       
68_spentry(builtin_plus)
69        __(test_two_fixnums(arg_y,arg_z,imm0))
70        __(bne 1f)
71        __(adds arg_z,arg_y,arg_z)
72        __(bxvc lr)
73        __(b _SPfix_overflow)
741:
75        __(jump_builtin(_builtin_plus,2))
76       
77_spentry(builtin_minus)
78        __(test_two_fixnums(arg_y,arg_z,imm0))
79        __(bne 1f)
80        __(subs arg_z,arg_y,arg_z)
81        __(bxvc lr)
82        __(b _SPfix_overflow)
831:
84        __(jump_builtin(_builtin_minus,2))
85
86_spentry(builtin_times)
87        __(test_two_fixnums(arg_y,arg_z,imm0))
88        __(bne 1f)
89        __(unbox_fixnum(imm2,arg_z))
90        __(unbox_fixnum(imm0,arg_y))
91        __(smull imm0,imm1,imm2,imm0)
92        __(b _SPmakes64)
93
941: __(jump_builtin(_builtin_times,2))
95
96_spentry(builtin_div)
97        __(jump_builtin(_builtin_div,2))
98
99_spentry(builtin_eq)
100        __(test_two_fixnums(arg_y,arg_z,imm0))
101        __(bne 1f)
102        __(cmp arg_y,arg_z)
103        __(mov arg_z,#nil_value)
104        __(addeq arg_z,arg_z,#t_offset)
105        __(bx lr)       
1061:
107        __(jump_builtin(_builtin_eq,2))
108                       
109_spentry(builtin_ne)
110        __(test_two_fixnums(arg_y,arg_z,imm0))
111        __(bne 1f)
112        __(cmp arg_y,arg_z)
113        __(mov arg_z,#nil_value)
114        __(addne arg_z,arg_z,#t_offset)
115        __(bx lr)
1161:
117        __(jump_builtin(_builtin_ne,2))
118
119_spentry(builtin_gt)
120        __(test_two_fixnums(arg_y,arg_z,imm0))
121        __(bne 1f)
122        __(cmp arg_y,arg_z)
123        __(mov arg_z,#nil_value)
124        __(addgt arg_z,arg_z,#t_offset)
125        __(bx lr)
1261:
127        __(jump_builtin(_builtin_gt,2))
128
129_spentry(builtin_ge)
130        __(test_two_fixnums(arg_y,arg_z,imm0))
131        __(bne 1f)
132        __(cmp arg_y,arg_z)
133        __(mov arg_z,#nil_value)
134        __(addge arg_z,arg_z,#t_offset)
135        __(bx lr)
1361:
137        __(jump_builtin(_builtin_ge,2))
138
139_spentry(builtin_lt)
140        __(test_two_fixnums(arg_y,arg_z,imm0))
141        __(bne 1f)
142        __(cmp arg_y,arg_z)
143        __(mov arg_z,#nil_value)
144        __(addgt arg_z,arg_z,#t_offset)
145        __(bx lr)
1461:
147        __(jump_builtin(_builtin_lt,2))
148
149_spentry(builtin_le)
150        __(test_two_fixnums(arg_y,arg_z,imm0))
151        __(bne 1f)
152        __(cmp arg_y,arg_z)
153        __(mov arg_z,#nil_value)
154        __(addle arg_z,arg_z,#t_offset)
155        __(bx lr)
1561:
157        __(jump_builtin(_builtin_le,2))
158
159_spentry(builtin_eql)
160        __(cmp arg_y,arg_z)
161        __(beq 1f)
162        __(extract_fulltag(imm0,arg_y))
163        __(extract_fulltag(imm1,arg_z))
164        __(cmp imm0,imm1)
165        __(bne 2f)
166        __(cmp imm0,#fulltag_misc)
167        __(bne 2f)
168        __(jump_builtin(_builtin_eql,2))
1691:      __(mov arg_z,#nil_value)
170        __(add arg_z,arg_z,#t_offset)
171        __(bx lr)
1722:      __(mov arg_z,#nil_value)
173        __(bx lr)
174       
175_spentry(builtin_length)
176        __(extract_typecode(imm0,arg_z))
177        __(cmp imm0,#min_vector_subtag)
178        __(ldreq arg_z,[arg_z,#vectorH.logsize])
179        __(bxeq lr)
180        __(blo 1f)
181        __(vector_length(arg_z,arg_z,imm0))
182        __(bx lr)
1831:      __(cmp imm0,#tag_list)
184        __(bne 8f)
185        __(mov temp2,#-1<<fixnum_shift)
186        __(mov temp0,arg_z) /* fast pointer  */
187        __(mov temp1,arg_z) /* slow pointer  */
1882:      __(cmp temp0,#nil_value)
189        __(add temp2,temp2,#fixnumone)
190        __(beq 9f)
191        __(extract_lisptag(imm0,temp0))
192        __(cmp imm0,#tag_list)
193        __(bne 8f)
194        __(_cdr(temp0,temp0))
195        __(tst temp2,#fixnumone)
196        __(beq 2b)
197        __(_cdr(temp1,temp1))
198        __(cmp temp1,temp0)
199        __(bne 2b)
2008:
201        __(jump_builtin(_builtin_length,1))
2029:      __(mov arg_z,temp2)
203        __(bx lr)       
204
205_spentry(builtin_seqtype)
206        __(extract_typecode(imm0,arg_z))
207        __(cmp imm0,#min_vector_subtag)
208        __(movge arg_z,#nil_value)
209        __(bxge lr)
210        __(cmp imm0,#tag_list)
211        __(moveq arg_z,#nil_value)
212        __(addeq arg_z,arg_z,#t_offset)
213        __(bxeq lr)
214        __(jump_builtin(_builtin_seqtype,1))
215
216/* This is usually inlined these days */
217_spentry(builtin_assq)
218        __(b 2f)
2191:      __(trap_unless_list(arg_z,imm0))
220        __(_car(arg_x,arg_z))
221        __(_cdr(arg_z,arg_z))
222        __(cmp arg_x,#nil_value)
223        __(beq 2f)
224        __(trap_unless_list(arg_x,imm0))
225        __(_car(temp0,arg_x))
226        __(cmp temp0,arg_y)
227        __(bne 2f)
228        __(mov arg_z,arg_x)
229        __(bx lr)
2302:      __(cmp arg_z,#nil_value)
231        __(bne 1b)
232        __(bx lr)
233 
234_spentry(builtin_memq)
235        __(cmp arg_z,nil_value)
236        __(b 2f)
2371:      __(trap_unless_list(arg_z,imm0))
238        __(_car(arg_x,arg_z))
239        __(_cdr(temp0,arg_z))
240        __(cmp arg_x,arg_y)
241        __(bxeq lr)
242        __(cmp temp0,nil_value)
243        __(mov arg_z,temp0)
2442:      __(bne 1b)
245        __(bx lr)
246
247_spentry(builtin_logbitp)
248/* Call out unless both fixnums,0 <=  arg_y < logbitp_max_bit  */
249        __(test_two_fixnums(arg_y,arg_z,imm0))
250        __(bne 1f)
251        __(cmp arg_y,#(nbits_in_word-fixnumshift)<<fixnumshift)
252        __(bhs 1f)
253        __(unbox_fixnum(imm0,arg_y))
254        __(mov imm1,#fixnum1)
255        __(tst arg_z,imm1,lsl imm0)
256        __(mov arg_z,#nil_value)
257        __(addne arg_z,arg_z,#t_offset)
258        __(bx lr)
2591:
260        __(jump_builtin(_builtin_logbitp,2))
261
262_spentry(builtin_logior)
263        __(orr imm0,arg_y,arg_z)
264        __(test_fixnum(imm0))
265        __(moveq arg_z,imm0)
266        __(bxeq lr)
267        __(jump_builtin(_builtin_logior,2))
268
269_spentry(builtin_logand)
270        __(test_two_fixnums(arg_y,arg_z,imm0))
271        __(andeq arg_z,arg_y,arg_z)
272        __(bxeq lr)
273        __(jump_builtin(_builtin_logand,2))
274         
275_spentry(builtin_ash)
276        __(test_two_fixnums(arg_y,arg_z,imm0))
277        __(bne 9f)
278        __(cmp arg_z,#0)
279        __(bgt 1f)
280        __(moveq arg_z,arg_y)
281        __(bxeq lr)
282        /* Shift right */
283        __(unbox_fixnum(imm2,arg_z))
284        __(rsb imm2,imm2,#0)
285        __(cmp imm2,#32)
286        __(movge imm2,#31)
287        __(mov arg_z,#-fixnumone)
288        __(and arg_z,arg_z,arg_y,lsr imm2)
289        __(bx lr)
290        /* shift left */
2911:      __(unbox_fixnum(imm0,arg_y))
292        __(unbox_fixnum(imm2,arg_z))
293        __(cmp imm2,#32)
294        __(moveq imm1,imm0)
295        __(moveq imm0,#0)
296        __(beq _SPmakes64)
297        __(bgt 9f)
298        __(rsb imm1,imm2,#32)
299        __(mov imm1,imm0,asr imm1)
300        __(mov imm0,imm0,lsl imm2)
301        __(b _SPmakes64)
3029: 
303        __(jump_builtin(_builtin_ash,2))
304                                       
305_spentry(builtin_negate)
306        __(test_fixnum(arg_z))
307        __(bne 1f)
308        __(rsbs arg_z,arg_z,#0)
309        __(bxvc lr)
310        __(b _SPfix_overflow)
3111:
312        __(jump_builtin(_builtin_negate,1))
313 
314_spentry(builtin_logxor)
315        __(test_two_fixnums(arg_y,arg_z,imm0))
316        __(eoreq arg_z,arg_y,arg_z)
317        __(bxeq lr)
318        __(jump_builtin(_builtin_logxor,2))
319
320_spentry(builtin_aref1)
321        __(extract_typecode(imm0,arg_y))
322        __(cmp imm0,#min_vector_subtag)
323        __(box_fixnum(arg_x,imm0))
324        __(bgt _SPsubtag_misc_ref)
325        __(jump_builtin(_builtin_aref1,2))
326
327_spentry(builtin_aset1)
328        __(extract_typecode(imm0,arg_x))
329        __(cmp imm0,#min_vector_subtag)
330        __(box_fixnum(temp0,imm0))
331        __(bgt _SPsubtag_misc_set)
332        __(jump_builtin(_builtin_aset1,3))
333                       
334
335        /*  Call nfn if it's either a symbol or function */
336_spentry(funcall)
337        __(funcall_nfn())
338
339/* Subprims for catch, throw, unwind_protect.  */
340
341
342_spentry(mkcatch1v)
343        __(mov imm2,#0)
344        __(mkcatch())
345        __(bx lr)
346
347
348_spentry(mkcatchmv)
349        __(mov imm2,#fixnum_one)
350        __(mkcatch())
351        __(bx lr)
352
353_spentry(mkunwind)
354        __(mov imm2,#-fixnumone)
355        __(mov imm1,#INTERRUPT_LEVEL_BINDING_INDEX)
356        __(ldr temp0,[rcontext,#tcr.tlb_pointer])
357        __(ldr arg_y,[temp0,#INTERRUPT_LEVEL_BINDING_INDEX])
358        __(ldr imm0,[rcontext,#tcr.db_link])
359        __(vpush1(arg_y))
360        __(vpush1(imm1))
361        __(vpush1(imm0))
362        __(str imm2,[temp0,#INTERRUPT_LEVEL_BINDING_INDEX])
363        __(str vsp,[rcontext,#tcr.db_link])
364        __(mov arg_z,#unbound_marker)
365        __(mov imm2,#fixnum_one)
366        __(mkcatch())
367        __(mov arg_z,arg_y)
368        __(b _SPbind_interrupt_level)
369       
370
371/* This never affects the symbol's vcell  */
372/* Non-null symbol in arg_y, new value in arg_z          */
373_spentry(bind)
374        __(ldr imm1,[arg_y,#symbol.binding_index])
375        __(ldr imm0,[rcontext,#tcr.tlb_limit])
376        __(cmp imm0,imm1)
377        __(uuo_tlb_too_small(ls,imm1))
378        __(cmp imm1,#0)
379        __(ldr imm2,[rcontext,#tcr.tlb_pointer])
380        __(ldr imm0,[rcontext,#tcr.db_link])
381        __(ldr temp1,[imm2,imm0])
382        __(beq 9f)
383        __(vpush1(temp1))
384        __(vpush1(imm1))
385        __(vpush1(imm0))
386        __(str arg_z,[imm2,imm1])
387        __(str vsp,[rcontext,#tcr.db_link])
388        __(bx lr)
3899:
390        __(mov arg_z,arg_y)
391        __(mov arg_y,#XSYMNOBIND)
392        __(set_nargs(2))
393        __(b _SPksignalerr)
394
395_spentry(conslist)
396        __(mov arg_z,#nil_value)
397        __(cmp nargs,#0)
398        __(b 2f)
3991:
400        __(vpop1(arg_y))
401        __(Cons(arg_z,arg_z,arg_z))
402        __(subs nargs,nargs,#fixnum_one)
4032:
404        __(bne 1b)
405        __(bx lr)
406
407/* do list*: last arg in arg_z, all others vpushed, nargs set to #args vpushed.  */
408/* Cons, one cons cell at at time.  Maybe optimize this later.  */
409
410_spentry(conslist_star)
411        __(cmp nargs,#0)
412        __(b 2f)
4131:
414        __(vpop1(arg_y))
415        __(Cons(arg_z,arg_y,arg_z))
416        __(subs nargs,nargs,fixnum_one)
4172:
418        __(bne 1b)
419        __(bx lr)
420
421_spentry(makes32)
422        __(adds imm1,imm0,imm0)
423        __(addsvc arg_z,imm1,imm1)
424        __(bxvc lr)
425        __(movc16(imm1,one_digit_bignum_header))
426        __(Misc_Alloc_Fixed(arg_z,imm1,aligned_bignum_size(1)))
427        __(str imm0,[arg_z,#misc_data_offset])
428        __(bx lr)
429
430/* Construct a lisp integer out of the 32-bit unsigned value in imm0 */
431
432
433_spentry(makeu32)
434        __(tst imm0,#0xe0000000)
435        __(box_fixnum(arg_z,imm0))
436        __(bxeq lr)
437        __(tst imm0,#0x80000000)
438        __(bne 2f)
439        __(movc16(imm1,one_digit_bignum_header))
440        __(Misc_Alloc_Fixed(arg_z,imm1,aligned_bignum_size(1)))
441        __(str imm0,[arg_z,#misc_data_offset])
442        __(bx lr)
4432:             
444        __(movc16(imm1,two_digit_bignum_header))
445        __(Misc_Alloc_Fixed(arg_z,imm1,aligned_bignum_size(2)))
446        __(str imm0,[arg_z,#misc_data_offset])
447        __(bx lr)
448
449
450/* arg_z has overflowed (by one bit) as the result of an addition or
451   subtraction. */
452/* Make a bignum out of it. */
453
454_spentry(fix_overflow)
455        __(unbox_fixnum(imm0,arg_z))
456        __(eor imm0,imm0,#0xc0000000)
457        __(b _SPmakes32)
458
459
460
461/*  Construct a lisp integer out of the 64-bit unsigned value in */
462/*           imm0 (low 32 bits) and imm1 (high 32 bits) */
463       
464_spentry(makeu64)
465        __(cmp imm1,#0)
466        __(beq _SPmakeu32)
467        __(blt 3f)
468        __(movc16(imm2,two_digit_bignum_header))
469        __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(2)))
470        __(str imm0,[arg_z,#misc_data_offset])
471        __(str imm1,[arg_z,#misc_data_offset+4])
472        __(bx lr)
4733:             
474        __(movc16(imm2,three_digit_bignum_header))
475        __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(3)))
476        __(str imm0,[arg_z,#misc_data_offset])
477        __(str imm1,[arg_z,#misc_data_offset+4])
478        __(bx lr)
479
480/*  Construct a lisp integer out of the 64-bit signed value in */
481/*        imm0 (low 32 bits) and imm1 (high 32 bits). */
482_spentry(makes64)
483        __(cmp imm1,imm0,asr #31) /* is imm1 sign extension of imm0 ? */
484        __(beq _SPmakes32)        /* forget imm1 if so */
485        __(movc16(imm2,two_digit_bignum_header))
486        __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(2)))
487        __(str imm0,[arg_z,#misc_data_offset])
488        __(str imm1,[arg_z,#misc_data_offset+4])
489        __(bx lr)
490
491
492
493
494
495
496/* funcall nfn, returning multiple values if it does.  */
497_spentry(mvpass)
498        __(subs imm0,nargs,#node_size*nargregs)
499        __(movge imm0,#0)
500        __(add imm0,vsp,imm0)
501        __(build_lisp_frame(temp1,imm0))
502        __(adr lr,C(ret1valn))
503        __(mov fn,#0)
504        __(funcall_nfn())
505
506/* ret1valn returns "1 multiple value" when a called function does not  */
507/* return multiple values.  Its presence on the stack (as a return address)  */
508/* identifies the stack frame to code which returns multiple values.  */
509
510_exportfn(C(ret1valn))
511        __(restore_lisp_frame(imm0))
512        __(vpush1(arg_z))
513        __(set_nargs(1))
514        __(bx lr)
515
516/* Come here to return multiple values when  */
517/* the caller's context isn't saved in a lisp_frame.  */
518/* lr, fn valid; temp0 = entry vsp  */
519
520_spentry(values)
521local_label(return_values): 
522        __(ref_global(imm0,ret1val_addr))
523        __(mov arg_z,#nil_value)
524        __(cmp imm0,lr)
525        __(beq 3f)
526        __(cmp nargs,#fixnum_one)
527        __(add imm0,nargs,vsp)
528        __(ldrge arg_z,[imm0,#-node_size])
529        __(mov vsp,temp0)
530        __(bx lr)
531
532
533/* Return multiple values to real caller.  */
5343:
535        __(ldr lr,[sp,#lisp_frame.savelr])
536        __(add imm1,nargs,vsp)
537        __(ldr imm0,[sp,#lisp_frame.savevsp])
538        __(ldr fn,[sp,#lisp_frame.savefn])
539        __(cmp imm1,imm0) /* a fairly common case  */
540        __(discard_lisp_frame())
541        __(bxeq lr) /* already in the right place  */
542        __(cmp nargs,#fixnum_one) /* sadly, a very common case  */
543        __(bne 4f)
544        __(ldr arg_z,[vsp,#0])
545        __(mov vsp,imm0)
546        __(vpush1(arg_z))
547        __(bx lr)
5484:
549        __(blt 6f)
550        __(mov temp1,#fixnum_one)
5515:
552        __(cmp temp1,nargs)
553        __(add temp1,temp1,#fixnum_one)
554        __(ldr arg_z,[imm1,#-node_size]!)
555        __(push1(arg_z,imm0))
556        __(bne 5b)
5576:
558        __(mov vsp,imm0)
559        __(bx lr)
560
561
562/* Come here with saved context on top of stack.  */
563_spentry(nvalret)
564        .globl C(nvalret)
565C(nvalret):
566        __(ldr lr,[sp,#lisp_frame.savelr])
567        __(ldr temp0,[sp,#lisp_frame.savevsp])
568        __(ldr fn,[sp,#lisp_frame.savefn])
569        __(discard_lisp_frame())
570        __(b local_label(return_values))                         
571
572/* Caller has pushed tag and 0 or more values; nargs = nvalues.  */
573/* Otherwise, process unwind-protects and throw to indicated catch frame.  */
574
575               
576 _spentry(throw)
577        __(ldr imm1,[rcontext, #tcr.catch_top])
578        __(mov imm0,#0) /* count intervening catch/unwind-protect frames.  */
579        __(cmp imm1,#0)
580        __(ldr temp0,[vsp,nargs])
581        __(beq local_label(_throw_tag_not_found))
582local_label(_throw_loop):
583        __(ldr temp1,[imm1,#catch_frame.catch_tag])
584        __(cmp temp0,temp1)
585        __(mov imm2,imm1)
586        __(ldr imm1,[imm1,#catch_frame.link])
587        __(beq C(_throw_found))
588        __(cmp imm1,#0)
589        __(add imm0,imm0,#fixnum_one)
590        __(bne local_label(_throw_loop))
591local_label(_throw_tag_not_found):
592        __(uuo_error_no_throw_tag(al,temp0))
593        __(str temp0,[vsp,nargs])
594        __(b _SPthrow)
595
596/* This takes N multiple values atop the vstack.  */
597_spentry(nthrowvalues)
598dnl         __(mov imm1,#1)
599dnl  __(mov imm4,imm0)
600dnl         __(str(imm1,tcr.unwinding(rcontext)))
601dnl local_label(_nthrowv_nextframe):
602dnl  __(subi imm4,imm4,fixnum_one)
603dnl  __(cmpri(cr1,imm4,0))
604dnl  __(ldr temp0,[rcontext,#tcr.catch_top])
605dnl  __(ldr imm1,[rcontext,#tcr.db_link])
606dnl  __(blt cr1,local_label(_nthrowv_done))
607dnl  __(ldr imm0,[temp0,#catch_frame.db_link])
608dnl  __(ldr imm3,[temp0,#catch_frame.link])
609dnl  __(cmpr(imm0,imm1))
610dnl  __(str(imm3,tcr.catch_top(rcontext)))
611dnl  __(ldr temp1,[temp0,#catch_frame.catch_tag])
612dnl  __(cmpri(cr7,temp1,unbound_marker))  /* unwind-protect ?  */
613dnl  __(ldr first_nvr,[temp0,#catch_frame.xframe])
614dnl  __(str(first_nvr,tcr.xframe(rcontext)))
615dnl  __(ldr sp,[temp0,#catch_frame.csp])
616dnl  __(beq local_label(_nthrowv_dont_unbind))
617dnl  __(mflr loc_pc)
618dnl         __(bl _SPunbind_to)
619dnl  __(mtlr loc_pc)
620dnl local_label(_nthrowv_dont_unbind):
621dnl  __(beq cr7,local_label(_nthrowv_do_unwind))
622dnl /* A catch frame.  If the last one, restore context from there.  */
623dnl  __(bne cr1,local_label(_nthrowv_skip))
624dnl  __(ldr imm0,[sp,#lisp_frame.savevsp])
625dnl  __(str(rzero,lisp_frame.savevsp(sp))) /* marker for stack overflow code  */
626dnl  __(add imm1,vsp,nargs)
627dnl  __(mov imm2,nargs)
628dnl  __(b local_label(_nthrowv_push_test))
629dnl local_label(_nthrowv_push_loop):
630dnl  __(ldru(temp1,-node_size(imm1)))
631dnl  __(push(temp1,imm0))
632dnl local_label(_nthrowv_push_test):
633dnl  __(cmp imm2,#0))
634dnl  __(subi imm2,imm2,fixnum_one)
635dnl  __(bne local_label(_nthrowv_push_loop))
636dnl  __(mov vsp,imm0)
637dnl         __(restore_catch_nvrs(temp0))
638dnl
639dnl local_label(_nthrowv_skip):
640dnl  __(la tsp,-(tsp_frame.fixed_overhead+fulltag_misc)(temp0))
641dnl  __(unlink(tsp))
642dnl  __(discard_lisp_frame())
643dnl  __(b local_label(_nthrowv_nextframe))
644dnl local_label(_nthrowv_do_unwind):
645dnl         /* This is harder.  Call the cleanup code with the multiple */
646dnl  /* values (and nargs, which is a fixnum.)  Remember the throw count  */
647dnl         /* (also a fixnum) as well.  */
648dnl         /* Save our caller's LR and FN in the csp frame created by the unwind-  */
649dnl         /* protect.  (Clever, eh ?)  */
650dnl  __(ldr first_nvr,[temp0,#catch_frame.xframe])
651dnl  __(str(first_nvr,tcr.xframe(rcontext)))
652dnl         __(restore_catch_nvrs(temp0))
653dnl  __(la tsp,-(tsp_frame.fixed_overhead+fulltag_misc)(temp0))
654dnl  __(unlink(tsp))
655dnl  __(ldr loc_pc,[sp,#lisp_frame.savelr])
656dnl  __(ldr nfn,[sp,#lisp_frame.savefn])
657dnl  __(mtctr loc_pc) /* cleanup code address.  */
658dnl  __(str(fn,lisp_frame.savefn(sp)))
659dnl  __(mflr loc_pc)
660dnl  __(mov fn,nfn)
661dnl  __(str(loc_pc,lisp_frame.savelr(sp)))
662dnl  __(dnode_align(imm0,nargs,tsp_frame.fixed_overhead+(2*node_size))) /* tsp overhead, nargs, throw count  */
663dnl  __(TSP_Alloc_Var_Boxed_nz(imm0,imm1))
664dnl  __(mov imm2,nargs)
665dnl  __(add imm1,nargs,vsp)
666dnl  __(la imm0,tsp_frame.data_offset(tsp))
667dnl  __(str(nargs,0(imm0)))
668dnl  __(b local_label(_nthrowv_tpushtest))
669dnl local_label(_nthrowv_tpushloop):
670dnl  __(ldru(temp0,-node_size(imm1)))
671dnl  __(stru(temp0,node_size(imm0)))
672dnl  __(subi imm2,imm2,fixnum_one)
673dnl local_label(_nthrowv_tpushtest):
674dnl  __(cmp imm2,#0)
675dnl  __(bne local_label(_nthrowv_tpushloop))
676dnl  __(stru(imm4,node_size(imm0)))
677dnl  __(ldr vsp,[sp,#lisp_frame.savevsp])
678dnl         /* Interrupts should be disabled here (we're calling and returning */
679dnl         /* from the cleanup form.  Clear the tcr.unwinding flag, so that */
680dnl         /* interrupts can be taken if they're enabled in the cleanup form.  */
681dnl         __(str(rzero,tcr.unwinding(rcontext)))       
682dnl  __(bctrl)
683dnl         __(mov imm1,#1)
684dnl  __(la imm0,tsp_frame.data_offset(tsp))
685dnl         __(str(imm1,tcr.unwinding(rcontext)))
686dnl  __(ldr fn,[sp,#lisp_frame.savefn])
687dnl  __(ldr loc_pc,[sp,#lisp_frame.savelr])
688dnl  __(discard_lisp_frame())
689dnl  __(mtlr loc_pc)
690dnl  __(ldr nargs,[imm0,#0])
691dnl  __(mov imm2,nargs)
692dnl  __(b local_label(_nthrowv_tpoptest))
693dnl local_label(_nthrowv_tpoploop):
694dnl  __(ldru(temp0,node_size(imm0)))
695dnl  __(vpush1(temp0))
696dnl  __(subi imm2,imm2,fixnum_one)
697dnl local_label(_nthrowv_tpoptest):
698dnl  __(cmp imm2,#0)
699dnl  __(bne local_label(_nthrowv_tpoploop))
700dnl  __(ldr imm4,[imm0,#node_size])
701dnl  __(unlink(tsp))
702dnl  __(b local_label(_nthrowv_nextframe))
703dnl local_label(_nthrowv_done):
704dnl         __(str(rzero,tcr.unwinding(rcontext)))
705dnl         /* Poll for a deferred interrupt.  That clobbers nargs (which we've */
706dnl         /* just expended a lot of effort to preserve), so expend a little *
707dnl         /* more effort. */
708dnl         __(mov imm4,nargs)
709dnl         __(check_pending_interrupt())
710dnl         __(mov nargs,imm4)
711dnl         __(bx lr)
712
713/* This is a (slight) optimization.  When running an unwind-protect, */
714/* save the single value and the throw count in the tstack frame. */
715/* Note that this takes a single value in arg_z.  */
716_spentry(nthrow1value)
717        __(mov imm1,#1)
718        __(mov temp2,imm0)
719        __(str imm1,[rcontext,#tcr.unwinding])
720        __(b C(nthrow1v))
721
722
723/* arg_z = symbol: bind it to its current value          */
724 _spentry(bind_self)
725        __(ldr imm1,[arg_z,#symbol.binding_index])
726        __(ldr imm0,[rcontext,#tcr.tlb_limit])
727        __(cmp imm1,#0)
728        __(beq 9f)
729        __(cmp imm0,imm1)
730        __(uuo_tlb_too_small(ls,imm1))
731        __(ldr temp2,[rcontext,#tcr.tlb_pointer])
732        __(ldr imm0,[rcontext,#tcr.db_link])
733        __(ldr temp1,[temp2,imm1])
734        __(cmp temp1,#no_thread_local_binding_marker)
735        __(movne temp0,temp1)
736        __(ldreq temp0,[arg_z,#symbol.vcell])
737        __(vpush1(temp1))   /* old tlb contents */
738        __(vpush1(imm1))    /* tlb index */
739        __(vpush1(imm0))
740        __(str temp0,[temp2,imm1])
741        __(str vsp,[rcontext,#tcr.db_link])
742        __(bx lr)
7439:      __(mov arg_y,#XSYMNOBIND)
744        __(set_nargs(2))
745        __(b _SPksignalerr)
746
747/* Bind symbol in arg_z to NIL                 */
748_spentry(bind_nil)
749        __(mov arg_y,arg_z)
750        __(mov arg_z,#nil_value)
751        __(b _SPbind)
752
753/* Bind symbol in arg_z to its current value;  trap if symbol is unbound */
754_spentry(bind_self_boundp_check)
755        __(ldr imm1,[arg_z,#symbol.binding_index])
756        __(ldr imm0,[rcontext,#tcr.tlb_limit])
757        __(cmp imm1,#0)
758        __(beq 9f)
759        __(cmp imm0,imm1)
760        __(uuo_tlb_too_small(ls,imm1))
761        __(ldr temp2,[rcontext,#tcr.tlb_pointer])
762        __(ldr imm0,[rcontext,#tcr.db_link])
763        __(ldr temp1,[temp2,imm1])
764        __(cmp temp1,#no_thread_local_binding_marker)
765        __(movne temp0,temp1)
766        __(ldreq temp0,[arg_z,#symbol.vcell])
767        __(cmp temp0,#unbound_marker)
768        __(uuo_error_unbound(eq,arg_z))
769        __(vpush1(temp1))   /* old tlb contents */
770        __(vpush1(imm1))    /* tlb index */
771        __(vpush1(imm0))
772        __(str temp0,[temp2,imm1])
773        __(str vsp,[rcontext,#tcr.db_link])
774        __(bx lr)
7759:      __(mov arg_y,#XSYMNOBIND)
776        __(set_nargs(2))
777        __(b _SPksignalerr)
778
779 
780/* The function pc_luser_xp() - which is used to ensure that suspended threads */
781/* are suspended in a GC-safe way - has to treat these subprims (which  */
782/* implement the EGC write-barrier) specially.  Specifically, a store that */
783/* might introduce an intergenerational reference (a young pointer stored  */
784/* in an old object) has to "memoize" that reference by setting a bit in  */
785/* the global "refbits" bitmap. */
786/* This has to happen atomically, and has to happen atomically wrt GC. */
787/* Note that updating a word in a bitmap is itself not atomic, unless we use */
788/* interlocked loads and stores. */
789
790
791/* For RPLACA and RPLACD, things are fairly simple: regardless of where we  */
792/* are in the function, we can do the store (even if it's already been done)  */
793/* and calculate whether or not we need to set the bit out-of-line.  (Actually */
794/* setting the bit needs to be done atomically, unless we're sure that other */
795/* threads are suspended.) */
796/* We can unconditionally set the suspended thread's PC to its LR. */
797
798        .globl C(egc_write_barrier_start)
799_spentry(rplaca)
800C(egc_write_barrier_start):     
801        __(cmp arg_z,arg_y)
802        __(_rplaca(arg_y,arg_z))
803        __(bxhs lr)
804        __(ref_global(temp0,ref_base))
805        __(sub imm0,arg_y,temp0)
806        __(mov imm0,imm0,lsr #dnode_shift)
807        __(ref_global(imm1,oldspace_dnode_count))
808        __(cmp imm0,imm1)
809        __(bxhs lr)
810        __(and imm2,imm0,#31)
811        __(mov imm1,#0x80000000)
812        __(mov imm1,imm1,lsr imm2)
813        __(mov imm0,imm0,lsr #bitmap_shift)
814        __(ref_global(temp0,refbits))
815        __(add temp0,temp0,imm0,lsl #word_shift)
8160:      __(ldrex imm2,[temp0])
817        __(orr imm2,imm2,imm1)
818        __(strex imm0,imm2,[temp0])
819        __(cmp imm0,#0)
820        __(bne 0b)       
821        __(bx lr)
822
823
824        .globl C(egc_rplacd)
825_spentry(rplacd)
826C(egc_rplacd):
827        __(cmp arg_z,arg_y)
828        __(_rplacd(arg_y,arg_z))
829        __(bxhs lr)
830        __(ref_global(temp0,ref_base))
831        __(sub imm0,arg_y,temp0)
832        __(mov imm0,imm0,lsr #dnode_shift)
833        __(ref_global(imm1,oldspace_dnode_count))
834        __(cmp imm0,imm1)
835        __(bxhs lr)
836        __(and imm2,imm0,#31)
837        __(mov imm1,#0x80000000)
838        __(mov imm1,imm1,lsr imm2)
839        __(mov imm0,imm0,lsr #bitmap_shift)
840        __(ref_global(temp0,refbits))
841        __(add temp0,temp0,imm0,lsl #word_shift)
8420:      __(ldrex imm2,[temp0])
843        __(orr imm2,imm2,imm1)
844        __(strex imm0,imm2,[temp0])
845        __(cmp imm0,#0)
846        __(bne 0b)       
847        __(bx lr)
848       
849
850/* Storing into a gvector can be handled the same way as storing into a CONS. */
851
852        .globl C(egc_gvset)
853_spentry(gvset)
854C(egc_gvset):
855        __(cmp arg_z,arg_x)
856        __(add imm0,arg_y,#misc_data_offset)
857        __(str arg_z,[arg_x,imm0])
858        __(bxhs lr)
859        __(add imm0,imm0,arg_x)
860        __(ref_global(temp0,ref_base))
861        __(sub imm0,imm0,temp0)
862        __(mov imm0,imm0,lsr #dnode_shift)
863        __(ref_global(imm1,oldspace_dnode_count))
864        __(cmp imm0,imm1)
865        __(bxhs lr)
866        __(and imm2,imm0,#31)
867        __(mov imm1,#0x80000000)
868        __(mov imm1,imm1,lsr imm2)
869        __(mov imm0,imm0,lsr #bitmap_shift)
870        __(ref_global(temp0,refbits))
871        __(add temp0,temp0,imm0,lsl #word_shift)
8720:      __(ldrex imm2,[temp0])
873        __(orr imm2,imm2,imm1)
874        __(strex imm0,imm2,[temp0])
875        __(cmp imm0,#0)
876        __(bne 0b)       
877        __(bx lr)
878
879       
880dnl /* This is a special case of storing into a gvector: if we need to memoize  */
881dnl /* the store, record the address of the hash-table vector in the refmap,  */
882dnl /* as well. */
883        .globl C(egc_set_hash_key)       
884_spentry(set_hash_key)
885C(egc_set_hash_key):
886dnl         __(cmplr(cr2,arg_z,arg_x))
887dnl         __(la imm0,misc_data_offset(arg_y))
888dnl         __(str arg_z,arg_x,imm0)
889dnl         __(blelr cr2)
890dnl         __(add imm0,imm0,arg_x)
891dnl         __(ref_global(imm2,ref_base))
892dnl         __(load_highbit(imm3))
893dnl         __(ref_global(imm1,oldspace_dnode_count))
894dnl         __(sub imm0,imm0,imm2)
895dnl         __(srri(imm0,imm0,dnode_shift))       
896dnl         __(cmplr(imm0,imm1))
897dnl         __(extract_bit_shift_count(imm4,imm0))
898dnl         __(srri(imm0,imm0,bitmap_shift))       
899dnl         __(srr(imm3,imm3,imm4))
900dnl         __(ref_global(imm2,refbits))
901dnl         __(bgelr)
902dnl         __(slri(imm0,imm0,word_shift))
903dnl         __(ldrx(imm1,imm2,imm0))
904dnl         __(and. imm1,imm1,imm3)
905dnl         __(bne 2f)       
906dnl 1:      __(lrarx(imm1,imm2,imm0))
907dnl         __(or imm1,imm1,imm3)
908dnl         __(strcx(imm1,imm2,imm0))
909dnl         __(bne- 1b)
910dnl         __(isync)
911dnl 2:             
912dnl         __(ref_global(imm1,ref_base))
913dnl         __(sub imm0,arg_x,imm1)
914dnl         __(srri(imm0,imm0,dnode_shift))
915dnl         __(load_highbit(imm3))
916dnl         __(extract_bit_shift_count(imm4,imm0))
917dnl         __(srri(imm0,imm0,bitmap_shift))
918dnl         __(srr(imm3,imm3,imm4))
919dnl         __(slri(imm0,imm0,word_shift))
920dnl         __(ldrx(imm1,imm2,imm0))
921dnl         __(and. imm1,imm1,imm3)
922dnl         __(bnelr)
923dnl 3:      __(lrarx(imm1,imm2,imm0))
924dnl         __(or imm1,imm1,imm3)
925dnl         __(strcx(imm1,imm2,imm0))
926dnl         __(bne- 3b)
927dnl         __(isync)
928dnl         __(bx lr)
929
930
931/*
932   Interrupt handling (in pc_luser_xp()) notes: 
933   If we are in this function and before the test which follows the
934   conditional (at egc_store_node_conditional), or at that test
935   and cr0`eq' is clear, pc_luser_xp() should just let this continue
936   (we either haven't done the store conditional yet, or got a
937   possibly transient failure.)  If we're at that test and the
938   cr0`EQ' bit is set, then the conditional store succeeded and
939   we have to atomically memoize the possible intergenerational
940   reference.  Note that the local labels 4 and 5 are in the
941   body of the next subprim (and at or beyond 'egc_write_barrier_end').
942
943   N.B: it's not possible to really understand what's going on just
944   by the state of the cr0`eq' bit.  A transient failure in the
945   conditional stores that handle memoization might clear cr0`eq'
946   without having completed the memoization.
947*/
948
949            .globl C(egc_store_node_conditional)
950            .globl C(egc_write_barrier_end)
951_spentry(store_node_conditional)
952C(egc_store_node_conditional):
953        __(vpop1(temp0))
954         
9551:      __(unbox_fixnum(imm2,temp0))
956        __(add imm2,imm2,arg_x)
957        __(ldrex temp1,[imm2])
958        __(cmp temp1,arg_y)
959        __(bne 5f)
960        __(strex imm0,arg_z,[imm2])
961        .globl C(egc_store_node_conditional_test)
962C(egc_store_node_conditional_test): 
963        __(cmp imm0,#0)
964        __(bne 1b)
965        __(cmp arg_z,arg_x)
966        __(blo 4f)
967
968        __(ref_global(imm0,ref_base))
969        __(ref_global(imm1,oldspace_dnode_count))
970        __(sub imm0,imm2,imm0)
971        __(mov imm0,imm0,lsr #dnode_shift)
972        __(cmp imm0,imm1)
973        __(bhs 4f)
974        __(and imm1,imm0,#31)
975        __(mov arg_x,#0x80000000)
976        __(mov imm1,arg_x,lsr imm1)
977        __(ref_global(temp0,refbits))
978        __(mov imm0,imm0,lsr #bitmap_shift)
979        __(add temp0,temp0,imm0,lsl #word_shift)
9802:      __(ldrex imm2,[temp0])
981        __(orr imm2,imm2,imm1)
982        __(strex imm0,imm2,[temp0])
983        __(cmp imm0,#0)
984        __(bne 2b)
985        __(b 4f)
986 
987/* arg_z = new value, arg_y = expected old value, arg_x = hash-vector,
988    vsp`0' = (boxed) byte-offset
989    Interrupt-related issues are as in store_node_conditional, but
990l    we have to do more work to actually do the memoization.*/
991_spentry(set_hash_key_conditional)
992        .globl C(egc_set_hash_key_conditional)
993C(egc_set_hash_key_conditional):
994dnl  __(cmplr(cr2,arg_z,arg_x))
995dnl  __(vpop(imm4))
996dnl  __(unbox_fixnum(imm4,imm4))
997dnl 1: __(lrarx(temp1,arg_x,imm4))
998dnl  __(cmpr(cr1,temp1,arg_y))
999dnl  __(bne cr1,5f)
1000dnl  __(strcx(arg_z,arg_x,imm4))
1001        .globl C(egc_set_hash_key_conditional_test)
1002C(egc_set_hash_key_conditional_test):
1003dnl  __(bne 1b)
1004dnl  __(isync)
1005dnl  __(add imm0,imm4,arg_x)
1006dnl  __(ref_global(imm2,ref_base))
1007dnl  __(ref_global(imm1,oldspace_dnode_count))
1008dnl  __(sub imm0,imm0,imm2)
1009dnl  __(load_highbit(imm3))
1010dnl  __(srri(imm0,imm0,dnode_shift))
1011dnl  __(cmplr(imm0,imm1))
1012dnl  __(extract_bit_shift_count(imm2,imm0))
1013dnl  __(srri(imm0,imm0,bitmap_shift))
1014dnl  __(srr(imm3,imm3,imm2))
1015dnl  __(ref_global(imm2,refbits))
1016dnl  __(bge 4f)
1017dnl  __(slri(imm0,imm0,word_shift))
1018dnl 2: __(lrarx(imm1,imm2,imm0))
1019dnl  __(or imm1,imm1,imm3)
1020dnl  __(strcx(imm1,imm2,imm0))
1021dnl  __(bne- 2b)
1022dnl  __(isync)
1023dnl  /* Memoize hash table header */ 
1024dnl         __(ref_global(imm1,ref_base))
1025dnl         __(sub imm0,arg_x,imm1)
1026dnl         __(srri(imm0,imm0,dnode_shift))
1027dnl         __(load_highbit(imm3))
1028dnl         __(extract_bit_shift_count(imm4,imm0))
1029dnl         __(srri(imm0,imm0,bitmap_shift))
1030dnl         __(srr(imm3,imm3,imm4))
1031dnl         __(slri(imm0,imm0,word_shift))
1032dnl         __(ldrx(imm1,imm2,imm0))
1033dnl         __(and. imm1,imm1,imm3)
1034dnl         __(bne 4f)
1035dnl 3:      __(lrarx(imm1,imm2,imm0))
1036dnl         __(or imm1,imm1,imm3)
1037dnl         __(strcx(imm1,imm2,imm0))
1038dnl         __(bne- 3b)
1039dnl         __(isync)
1040C(egc_write_barrier_end):
10414:      __(mov arg_z,#nil_value)
1042        __(add arg_z,arg_z,#t_offset)
1043        __(bx lr)
10445:      __(clrex)
1045        __(mov arg_z,#nil_value)
1046        __(bx lr)
1047
1048
1049
1050
1051       
1052/* We always have to create a stack frame (even if nargs is 0), so the compiler  */
1053/* doesn't get confused.  */
1054_spentry(stkconslist)
1055        __(mov arg_z,#nil_value)
1056C(stkconslist_star):           
1057        __(mov temp2,nargs,lsl #1)
1058        __(add temp2,temp2,#node_size)
1059        __(mov imm0,temp2,lsl #num_subtag_bits-word_shift)
1060        __(orr imm0,imm0,#subtag_u32_vector)
1061        __(stack_allocate_zeroed_ivector(imm0,temp2))
1062        __(mov imm0,#subtag_simple_vector)
1063        __(strb imm0,[sp,#0])
1064        __(add imm1,sp,#dnode_size+fulltag_cons)
1065        __(cmp nargs,#0)
1066        __(b 4f)
10671:      __(vpop1(temp0))
1068        __(_rplaca(imm1,temp0))
1069        __(_rplacd(imm1,arg_z))
1070        __(mov arg_z,imm1)
1071        __(add imm1,imm1,#cons.size)
1072        __(subs nargs,nargs,#node_size)
10734:
1074        __(bne 1b)
1075        __(bx lr)
1076 
1077/* do list*: last arg in arg_z, all others vpushed,  */
1078/* nargs set to #args vpushed.  */
1079_spentry(stkconslist_star)
1080        __(b C(stkconslist_star))
1081
1082/* Make a stack-consed simple-vector out of the NARGS objects  */
1083/* on top of the vstack; return it in arg_z.  */
1084_spentry(mkstackv)
1085        __(dnode_align(imm1,nargs,node_size))
1086        __(mov imm0,nargs,lsl #num_subtag_bits-fixnumshift)
1087        __(orr imm0,imm0,#subtag_u32_vector)
1088        __(stack_allocate_zeroed_ivector(imm0,imm1))
1089        __(mov imm0,#subtag_simple_vector)
1090        __(strb imm0,[sp,#0])
1091        __(add arg_z,sp,#fulltag_misc)
1092        __(add imm0,arg_z,#misc_data_offset)
1093        __(add imm1,imm0,nargs)
1094        __(b 4f)
10953:      __(vpop1(arg_y))
1096        __(str arg_y,[imm1,#-node_size]!)
1097        __(sub nargs,nargs,#node_size)
10984:      __(cmp nargs,#0)
1099        __(bne 3b)
1100        __(bx lr)
1101       
1102_spentry(setqsym)
1103        __(ldr imm0,[arg_y,#symbol.flags])
1104        __(tst imm0,#sym_vbit_const_mask)
1105        __(beq _SPspecset)
1106        __(mov arg_z,arg_y)
1107        __(mov arg_y,#XCONST)
1108        __(set_nargs(2))
1109        __(b _SPksignalerr)
1110
1111
1112
1113_spentry(progvsave)
1114dnl  /* Error if arg_z isn't a proper list.  That's unlikely, */
1115dnl  /* but it's better to check now than to crash later. */
1116dnl 
1117dnl  __(cmp arg_z,#nil_value)
1118dnl  __(mov arg_x,arg_z) /* fast  */
1119dnl  __(mov temp1,arg_z) /* slow  */
1120dnl  __(beq 9f)  /* Null list is proper  */
1121dnl 0:
1122dnl  __(trap_unless_list(arg_x,imm0))
1123dnl  __(_cdr(temp2,arg_x)) /* (null (cdr fast)) ?  */
1124dnl  __(cmpri(cr3,temp2,nil_value))
1125dnl  __(trap_unless_list(temp2,imm0,cr0))
1126dnl  __(_cdr(arg_x,temp2))
1127dnl  __(beq cr3,9f)
1128dnl  __(_cdr(temp1,temp1))
1129dnl  __(cmpr(arg_x,temp1))
1130dnl  __(bne 0b)
1131dnl  __(mov arg_y,#XIMPROPERLIST)
1132dnl  __(set_nargs(2))
1133dnl  __(b _SPksignalerr)
1134dnl 9: /* Whew   */
1135dnl 
1136dnl         /* Next, determine the length of arg_y.  We  */
1137dnl         /* know that it's a proper list.  */
1138dnl  __(mov imm0,#-node_size)
1139dnl  __(mov arg_x,arg_y)
1140dnl 1:
1141dnl  __(cmp arg_x,#nil_value)
1142dnl  __(la imm0,node_size(imm0))
1143dnl  __(_cdr(arg_x,arg_x))
1144dnl  __(bne 1b)
1145dnl  /* imm0 is now (boxed) triplet count.  */
1146dnl  /* Determine word count, add 1 (to align), and make room.  */
1147dnl  /* if count is 0, make an empty tsp frame and exit  */
1148dnl  __(cmp imm0,#0)
1149dnl  __(add imm1,imm0,imm0)
1150dnl  __(add imm1,imm1,imm0)
1151dnl         __(dnode_align(imm1,imm1,node_size))
1152dnl  __(bne+ 2f)
1153dnl   __(TSP_Alloc_Fixed_Boxed(2*node_size))
1154dnl   __(bx lr)
1155dnl 2:
1156dnl  __(la imm1,tsp_frame.fixed_overhead(imm1)) /* tsp header  */
1157dnl  __(TSP_Alloc_Var_Boxed_nz(imm1,imm2))
1158dnl  __(str(imm0,tsp_frame.data_offset(tsp)))
1159dnl  __(ldr imm2,[tsp,#tsp_frame.backlink])
1160dnl  __(mov arg_x,arg_y)
1161dnl  __(ldr imm1,[rcontext,#tcr.db_link])
1162dnl         __(ldr imm3,[rcontext,#tcr.tlb_limit])
1163dnl 3:
1164dnl         __(cmpri(cr1,arg_z,nil_value))
1165dnl  __(_car(temp0,arg_x))
1166dnl         __(ldr imm0,[temp0,#symbol.binding_index])
1167dnl  __(_cdr(arg_x,arg_x))
1168dnl         __(trlle(imm3,imm0))
1169dnl         __(ldr imm4,[rcontext,#tcr.tlb_pointer]) /* Need to reload after trap  */
1170dnl         __(ldrx(temp3,imm4,imm0))
1171dnl  __(cmp arg_x,#nil_value)
1172dnl         __(mov temp2,#unbound_marker)
1173dnl         __(beq cr1,4f)
1174dnl  __(_car(temp2,arg_z))
1175dnl  __(_cdr(arg_z,arg_z))
1176dnl 4:      __(push(temp3,imm2))
1177dnl  __(push(imm0,imm2))
1178dnl  __(push(imm1,imm2))
1179dnl         __(str temp2,imm4,imm0)
1180dnl  __(mov imm1,imm2)
1181dnl  __(bne 3b)
1182dnl  __(str(imm2,tcr.db_link(rcontext)))
1183dnl  __(bx lr)
1184dnl
1185dnl 
1186       
1187/* Allocate a uvector on the  stack.  (Push a frame on the stack and  */
1188/* heap-cons the object if there's no room on the stack.)  */
1189_spentry(stack_misc_alloc)
1190        __(tst arg_y,#unsigned_byte_24_mask)
1191        __(uuo_error_reg_not_xtype(ne,arg_y,xtype_unsigned_byte_24))
1192        __(unbox_fixnum(imm0,arg_z))
1193        __(extract_fulltag(imm1,imm0))
1194        __(cmp imm1,#fulltag_nodeheader)
1195        __(bne 1f)
1196        __(dnode_align(imm1,arg_y,node_size))
1197        __(cmp imm1,#stack_alloc_limit)
1198        __(bge 9f)
1199        __(mov imm0,#subtag_u32_vector)
1200        __(orr imm0,imm0,arg_y,lsl #num_subtag_bits-fixnumshift)
1201        __(stack_allocate_zeroed_ivector(imm0,imm1))
1202        __(unbox_fixnum(imm0,arg_z))
1203        __(strb imm0,[sp])
1204        __(add arg_z,sp,#fulltag_misc)
1205        __(bx lr)
12061:      __(mov imm0,arg_y,lsl #num_subtag_bits-fixnumshift)
1207        __(orr imm0,imm0,arg_z,lsr #fixnumshift)
1208        __(cmp arg_z,#max_32_bit_ivector_subtag<<fixnumshift)
1209        __(movle imm1,arg_y)
1210        __(ble 8f)
1211        __(cmp arg_z,#max_8_bit_ivector_subtag<<fixnumshift)
1212        __(movle imm1,arg_y,lsr #fixnumshift)
1213        __(ble 8f)
1214        __(cmp arg_z,#max_16_bit_ivector_subtag<<fixnumshift)
1215        __(movle imm1,arg_y,lsr #1)
1216        __(ble 8f)
1217        __(cmp arg_z,#subtag_double_float)
1218        __(moveq imm1,arg_y,lsl #1)
1219        __(addeq imm1,imm1,#node_size)
1220        __(addne imm1,arg_y,#7<<fixnumshift)
1221        __(movne imm1,imm1,lsr#3+fixnumshift)
12228:      __(dnode_align(imm1,imm1,node_size))
1223        __(cmp imm1,#stack_alloc_limit)
1224        __(bhs 9f)
1225        __(stack_allocate_zeroed_ivector(imm0,imm1))
1226        __(add arg_z,sp,#fulltag_misc)
1227        __(bx lr)
12289:
1229
1230/* Too large to safely fit on tstack.  Heap-cons the vector, but make  */
1231/* sure that there's an empty tsp frame to keep the compiler happy.  */
12320:
1233        __(movc16(imm0,make_header(1,subtag_u32_vector)))
1234        __(mov imm1,#0)
1235        __(stmdb sp!,{imm0,imm1})
1236        __(b _SPmisc_alloc)
1237
1238
1239/* subtype (boxed, of course) is vpushed, followed by nargs bytes worth of  */
1240/* initial-contents.  Note that this can be used to cons any type of initialized  */
1241/* node-header'ed misc object (symbols, closures, ...) as well as vector-like  */
1242/* objects.  */
1243
1244_spentry(gvector)
1245        __(sub nargs,nargs,#node_size)
1246        __(ldr arg_z,[vsp,nargs])
1247        __(unbox_fixnum(imm0,arg_z))
1248        __(orr imm0,imm0,nargs,lsl #num_subtag_bits-fixnum_shift)
1249        __(dnode_align(imm1,nargs,node_size))
1250        __(Misc_Alloc(arg_z,imm0,imm1))
1251        __(mov imm1,nargs)
1252        __(add imm2,imm1,#misc_data_offset)
1253        __(b 2f)
12541:
1255        __(str temp0,[arg_z,imm2])
12562:
1257        __(sub imm1,imm1,#node_size)
1258        __(cmp imm1,#0)
1259        __(sub imm2,imm2,#node_size)
1260        __(vpop1(temp0))        /* Note the intentional fencepost: */
1261                                /* discard the subtype as well.  */
1262        __(bge 1b)
1263        __(bx lr)
1264
1265_spentry(fitvals)
1266        __(subs imm0,imm0,nargs)
1267        __(mov imm1,#nil_value)
1268        __(sublt vsp,vsp,imm0)
1269        __(bxlt lr)
1270        __(b 2f)
12711:
1272        __(subs imm0,imm0,#node_size)
1273        __(vpush1(imm1))       
1274        __(add nargs,nargs,#node_size)
12752:
1276        __(bne 1b)
1277        __(bx lr)
1278
1279
1280_spentry(nthvalue)
1281        __(add imm0,vsp,nargs)
1282        __(ldr imm1,[imm0,#0])
1283        __(cmp imm1,nargs) /*  do unsigned compare:  if (n < 0) => nil.  */
1284        __(mov arg_z,#nil_value)
1285        __(rsb imm1,imm1,#0)
1286        __(sub imm1,imm1,#node_size)
1287        __(ldrlo arg_z,[imm0,imm1])
1288        __(add vsp,imm0,#node_size)
1289        __(bx lr)
1290
1291/* Provide default (NIL) values for &optional arguments; imm0 is  */
1292/* the (fixnum) upper limit on the total of required and &optional  */
1293/* arguments.  nargs is preserved, all arguments wind up on the  */
1294/* vstack.  */
1295_spentry(default_optional_args)
1296        __(vpush_argregs())
1297        __(cmp nargs,imm0)
1298        __(mov arg_z,#nil_value)
1299        __(mov imm1,nargs)
1300        __(bxhs lr)
13011:
1302        __(add imm1,imm1,#fixnum_one)
1303        __(cmp imm1,imm0)
1304        __(vpush1(arg_z))
1305        __(bne 1b)
1306        __(bx lr)
1307
1308/* Indicate whether &optional arguments were actually supplied.  nargs  */
1309/* contains the actual arg count (minus the number of required args);  */
1310/* imm0 contains the number of &optional args in the lambda list.  */
1311/* Note that nargs may be > imm0 if &rest/&key is involved.  */
1312_spentry(opt_supplied_p)
1313        __(mov imm1,#0)
1314        __(mov arg_x,#nil_value)
1315        __(add arg_x,arg_x,#t_offset)       
13161:     
1317        /* (vpush (< imm1 nargs))  */
1318        __(cmp imm1,nargs)
1319        __(add imm1,imm1,#fixnumone)
1320        __(subeq arg_x,arg_x,#t_offset)
1321        __(vpush1(arg_x))
1322        __(cmp imm1,imm0)
1323        __(bne 1b)
1324        __(bx lr)
1325
1326/* Cons a list of length nargs  and vpush it.  */
1327/* Use this entry point to heap-cons a simple &rest arg.  */
1328_spentry(heap_rest_arg)
1329        __(vpush_argregs())
1330        __(movs imm1,nargs)
1331        __(mov arg_z,#nil_value)
1332        __(b 2f)
13331:
1334        __(vpop1(arg_y))
1335        __(Cons(arg_z,arg_y,arg_z))
1336        __(subs imm1,imm1,#fixnum_one)
13372:
1338        __(bne 1b)
1339        __(vpush1(arg_z))
1340        __(bx lr)
1341
1342 
1343/* And this entry point when the argument registers haven't yet been  */
1344/* vpushed (as is typically the case when required/&rest but no  */
1345/* &optional/&key.)  */
1346_spentry(req_heap_rest_arg)
1347        __(vpush_argregs())
1348        __(subs imm1,nargs,imm0)
1349        __(mov arg_z,#nil_value)
1350        __(b 2f)
13511:
1352        __(vpop1(arg_y))
1353        __(Cons(arg_z,arg_y,arg_z))
1354        __(subs imm1,imm1,#fixnum_one)
13552:
1356        __(bgt 1b)
1357        __(vpush1(arg_z))
1358        __(bx lr)
1359
1360/* Here where argregs already pushed */
1361_spentry(heap_cons_rest_arg)
1362        __(subs imm1,nargs,imm0)
1363        __(mov arg_z,#nil_value)
1364        __(b 2f)
13651:
1366        __(vpop1(arg_y))
1367        __(Cons(arg_z,arg_y,arg_z))
1368        __(subs imm1,imm1,#fixnum_one)
13692:
1370        __(bgt 1b)
1371        __(vpush1(arg_z))
1372        __(bx lr)
1373
1374
1375_spentry(check_fpu_exception)
1376
1377_spentry(discard_stack_object)
1378        new_local_labels()       
1379        __(ldr imm0,[sp,#0])
1380        __(cmp imm0,#stack_alloc_marker)
1381        __(ldreq sp,[sp,#node_size])
1382        __(bxeq lr)
1383        __(cmp imm0,#lisp_frame_marker)
1384        __(extract_fulltag(imm1,imm0))
1385        __(addeq sp,sp,#lisp_frame.size)
1386        __(bxeq lr)
1387        __(cmp imm1,#fulltag_immheader)
1388        __(and imm1,imm0,#subtag_mask)
1389        __(bic imm0,imm0,#subtag_mask)
1390        __(beq local_label(ivector))
1391local_label(word):
1392        __(mov imm0,imm0,lsr #num_subtag_bits-word_shift)
1393local_label(out):       
1394        __(dnode_align(imm0,imm0,node_size))
1395        __(add sp,sp,imm0)
1396        __(bx lr)
1397local_label(ivector):     
1398        __(cmp imm1,#max_32_bit_ivector_subtag)
1399        __(bls local_label(word))       
1400        __(cmp imm1,#max_8_bit_ivector_subtag)
1401        __(movls imm0,imm0,lsr #num_subtag_bits)
1402        __(bls local_label(out))
1403        __(cmp imm1,#max_16_bit_ivector_subtag)
1404        __(movls imm0,imm0,lsr #num_subtag_bits-1)
1405        __(bls local_label(out))
1406        __(cmp imm1,#subtag_bit_vector)
1407        __(moveq imm0,imm0,lsr #num_subtag_bits)
1408        __(addeq imm0,imm0,#7)
1409        __(moveq imm0,imm0,lsr #3)
1410        __(beq local_label(out))
1411        /* The infamous 'stack-consed double-float vector' case */
1412        __(mov imm0,imm0,lsr #num_subtag_bits-dnode_shift)
1413        __(b local_label(out))
1414
1415
1416       
1417/* Signal an error synchronously, via %ERR-DISP.  */
1418/* If %ERR-DISP isn't fbound, it'd be nice to print a message  */
1419/* on the C runtime stderr.  */
1420 
1421_spentry(ksignalerr)
1422        __(ref_nrs_symbol(fname,errdisp,imm0))
1423        __(jump_fname)
1424
1425/* As in the heap-consed cases, only stack-cons the &rest arg  */
1426_spentry(stack_rest_arg)
1427        __(mov imm0,#0)
1428        __(vpush_argregs())
1429        __(b _SPstack_cons_rest_arg)
1430
1431_spentry(req_stack_rest_arg)
1432        __(vpush_argregs())
1433        __(b _SPstack_cons_rest_arg)
1434
1435_spentry(stack_cons_rest_arg)
1436        __(sub imm1,nargs,imm0)
1437        __(cmp imm1,#0)
1438        __(mov arg_z,#nil_value)
1439        __(ble 2f)  /* always temp-push something.  */
1440        __(add imm1,imm1,imm1)
1441        __(mov temp0,imm1)
1442        __(add imm1,imm1,#node_size)
1443        __(dnode_align(imm0,imm1,node_size))
1444        __(mov imm1,imm1,lsl #num_subtag_bits-fixnumshift)
1445        __(orr imm1,imm1,#subtag_u32_vector)
1446        __(cmp imm1,#stack_alloc_limit)
1447        __(bge 3f)
1448        __(stack_allocate_zeroed_ivector(imm1,imm0))
1449        __(mov imm0,#subtag_simple_vector)
1450        __(strb imm0,[sp])
1451        __(add imm0,sp,#dnode_size+fulltag_cons)
14521:
1453        __(subs temp0,temp0,#fixnumone)
1454        __(vpop1(arg_x))
1455        __(_rplacd(imm0,arg_z))
1456        __(_rplaca(imm0,arg_x))
1457        __(mov arg_z,imm0)
1458        __(add imm0,imm0,#cons.size)
1459        __(bne 1b)
1460        __(vpush1(arg_z))
1461        __(bx lr)
14622:
1463        __(movc16(imm0,make_header(1,subtag_u32_vector)))
1464        __(mov imm1,#0)
1465        __(stmdb sp!,{imm0,imm1})
1466        __(vpush1(arg_z))
1467        __(bx lr)
14683:
1469        __(movc16(imm0,make_header(1,subtag_u32_vector)))
1470        __(mov imm1,#0)
1471        __(stmdb sp!,{imm0,imm1})
1472        __(b _SPheap_cons_rest_arg)
1473
1474       
1475/* Prepend all but the first three (entrypoint, closure code, fn) and last two  */
1476/* (function name, lfbits) elements of nfn to the "arglist".  */
1477/* functions which take "inherited arguments" work consistently  */
1478/* even in cases where no closure object is created.  */
1479_spentry(call_closure)       
1480        __(cmp nargs,nargregs<<fixnumshift)
1481        __(vector_length(imm0,nfn,imm0))
1482        __(sub imm0,imm0,#5<<fixnumshift) /* imm0 = inherited arg count  */
1483        __(ble local_label(no_insert))
1484        /* Some arguments have already been vpushed.  Vpush imm0's worth  */
1485        /* of NILs, copy those arguments that have already been vpushed from  */
1486        /* the old TOS to the new, then insert all of the inerited args  */
1487        /* and go to the function.  */
1488        __(vpush_all_argregs())
1489        __(mov arg_x,imm0)
1490        __(mov arg_y,#nil_value)
1491local_label(push_nil_loop):
1492        __(subs arg_x,arg_x,#fixnumone)
1493        __(vpush1(arg_y))
1494        __(bne local_label(push_nil_loop))
1495        __(add arg_y,vsp,imm0)
1496        __(mov imm1,#0)
1497local_label(copy_already_loop):
1498        __(ldr arg_x,[vsp,imm1])
1499        __(str arg_x,[arg_y,imm1])
1500        __(add imm1,imm1,#fixnumone)
1501        __(cmp imm1,imm0)
1502        __(bne local_label(copy_already_loop))
1503        __(mov imm1,#misc_data_offset+(3<<fixnumshift))
1504        __(add arg_y,vsp,nargs)
1505        __(add arg_y,arg_y,imm0)
1506local_label(insert_loop):
1507        __(subs imm0,imm0,#fixnumone)
1508        __(ldr fname,[nfn,imm1])
1509        __(add imm1,imm1,#fixnumone)
1510        __(add nargs,nargs,#fixnumone)
1511        __(push1(fname,arg_y))
1512        __(bne local_label(insert_loop))
1513        __(vpop_all_argregs())
1514        __(b local_label(go))
1515local_label(no_insert):
1516/* nargregs or fewer args were already vpushed.  */
1517/* if exactly nargregs, vpush remaining inherited vars.  */
1518        __(cmp nargs,#nargregs<<fixnumshift)
1519        __(add imm1,imm0,#misc_data_offset+(3<<fixnumshift))
1520        __(bne local_label(set_regs))
1521local_label(vpush_remaining):
1522        __(mov imm1,#misc_data_offset+(3<<fixnumshift))
1523local_label(vpush_remaining_loop):             
1524        __(ldr fname,[nfn,imm1])
1525        __(add imm1,imm1,#fixnum_one)
1526        __(vpush1(fname))
1527        __(subs imm0,imm0,#fixnum_one)
1528        __(add nargs,nargs,#fixnum_one)
1529        __(bne  local_label(vpush_remaining_loop))
1530        __(b local_label(go))
1531local_label(set_regs):
1532        /* if nargs was > 1 (and we know that it was < 3), it must have  */
1533        /* been 2.  Set arg_x, then vpush the remaining args.  */
1534        __(cmp nargs,#fixnumone)
1535        __(ble local_label(set_y_z))
1536local_label(set_arg_x):
1537        __(subs imm0,imm0,#fixnum_one)
1538        __(sub imm1,imm1,#fixnum_one)
1539        __(ldr arg_x,[nfn,imm1])
1540        __(add nargs,nargs,#fixnum_one)
1541        __(bne local_label(vpush_remaining))
1542        __(b local_label(go))
1543        /* Maybe set arg_y or arg_z, preceding args  */
1544local_label(set_y_z):
1545        __(cmp nargs,#fixnumone)
1546        __(bne local_label(set_arg_z))
1547        /* Set arg_y, maybe arg_x, preceding args  */
1548local_label(set_arg_y):
1549        __(subs imm0,imm0,fixnum_one)
1550        __(sub imm1,imm1,#fixnum_one)
1551        __(ldr arg_y,[nfn,imm1])
1552        __(add nargs,nargs,#fixnum_one)
1553        __(bne local_label(set_arg_x))
1554        __(b local_label(go))
1555local_label(set_arg_z):
1556        __(subs imm0,imm0,#fixnum_one)
1557        __(sub imm1,imm1,#fixnum_one)
1558        __(ldr arg_z,[nfn,imm1])
1559        __(add nargs,nargs,#fixnum_one)
1560        __(bne local_label(set_arg_y))
1561 
1562local_label(go):
1563        __(vrefr(nfn,nfn,2))
1564        __(ldr pc,[nfn,#_function.entrypoint])
1565
1566
1567/* Everything up to the last arg has been vpushed, nargs is set to  */
1568/* the (boxed) count of things already pushed.  */
1569/* On exit, arg_x, arg_y, arg_z, and nargs are set as per a normal  */
1570/* function call (this may require vpopping a few things.)  */
1571/* ppc2-invoke-fn assumes that temp1 is preserved here.  */
1572_spentry(spreadargz)
1573        __(extract_lisptag(imm1,arg_z))
1574        __(cmp arg_z,#nil_value)
1575        __(mov imm0,#0)
1576        __(mov arg_y,arg_z)  /*  save in case of error  */
1577        __(beq 2f)
15781:
1579        __(cmp imm1,#tag_list)
1580        __(bne 3f)
1581        __(_car(arg_x,arg_z))
1582        __(_cdr(arg_z,arg_z))
1583        __(cmp arg_z,#nil_value)
1584        __(extract_lisptag(imm1,arg_z))
1585        __(vpush1(arg_x))
1586        __(add imm0,imm0,#fixnum_one)
1587        __(bne 1b)
15882:
1589        __(adds  nargs,nargs,imm0)
1590        __(bxeq lr)
1591        __(vpop_argregs_nz)
1592        __(bx lr)
1593       
1594        /*  Discard whatever's been vpushed already, complain.  */
15953: 
1596        __(add vsp,vsp,imm0)
1597        __(mov arg_z,arg_y)  /* recover original arg_z  */
1598        __(mov arg_y,#XNOSPREAD)
1599        __(set_nargs(2))
1600        __(b _SPksignalerr)
1601
1602/* Tail-recursively funcall temp0.  */
1603/* Pretty much the same as the tcallsym* cases above.  */
1604_spentry(tfuncallgen)
1605        __(cmp nargs,#nargregs<<fixnumshift)
1606        __(ldr lr,[sp,#lisp_frame.savelr])
1607        __(ldr fn,[sp,#lisp_frame.savefn])
1608        __(ble 2f)
1609        __(ldr imm0,[sp,#lisp_frame.savevsp])
1610        __(discard_lisp_frame())
1611        /* can use temp0 as a temporary  */
1612        __(sub imm1,nargs,#nargregs<<fixnumshift)
1613        __(add imm1,imm1,vsp)
16141:
1615        __(ldr temp0,[imm1,#-node_size]!)
1616        __(cmp imm1,vsp)
1617        __(push1(temp2,imm0))
1618        __(bne 1b)
1619        __(mov vsp,imm0)
1620        __(funcall_nfn())
16212:
1622        __(ldr vsp,[sp,#lisp_frame.savevsp])
1623        __(discard_lisp_frame())
1624        __(funcall_nfn())
1625
1626
1627/* Some args were vpushed.  Slide them down to the base of  */
1628/* the current frame, then do funcall.  */
1629_spentry(tfuncallslide)
1630        __(restore_lisp_frame(imm0))
1631        /* can use temp0 as a temporary  */
1632        __(sub imm1,nargs,#nargregs<<fixnumshift)
1633        __(add imm1,imm1,vsp)
16341:
1635        __(ldr temp0,[imm1,#-node_size]!)
1636        __(cmp imm1,vsp)
1637        __(push1(temp0,imm0))
1638        __(bne 1b)
1639        __(mov vsp,imm0)
1640        __(funcall_nfn())
1641
1642/* No args were vpushed; recover saved context & do funcall  */
1643_spentry(tfuncallvsp)
1644        __(restore_lisp_frame(imm0))
1645        __(funcall_nfn())
1646
1647/* Tail-recursively call the (known symbol) in fname.  */
1648/* In the general case, we don't know if any args were  */
1649/* vpushed or not.  If so, we have to "slide" them down  */
1650/* to the base of the frame.  If not, we can just restore  */
1651/* vsp, lr, fn from the saved lisp frame on the control stack.  */
1652_spentry(tcallsymgen)
1653        __(cmp nargs,#nargregs<<fixnumshift)
1654        __(ldr lr,[sp,#lisp_frame.savelr])
1655        __(ldr fn,[sp,#lisp_frame.savefn])
1656        __(ble 2f)
1657
1658        __(ldr imm0,[sp,#lisp_frame.savevsp])
1659        __(discard_lisp_frame())
1660        /* can use nfn (= temp2) as a temporary  */
1661        __(sub imm1,nargs,#nargregs<<fixnumshift)
1662        __(add imm1,imm1,vsp)
16631:
1664        __(ldr temp2,[imm1,#-node_size]!)
1665        __(cmp imm1,vsp)
1666        __(push1(temp2,imm0))
1667        __(bne 1b)
1668        __(mov vsp,imm0)
1669        __(jump_fname)
1670 
16712: 
1672        __(ldr vsp,[sp,#lisp_frame.savevsp])
1673        __(discard_lisp_frame())
1674        __(jump_fname)
1675
1676
1677/* Some args were vpushed.  Slide them down to the base of  */
1678/* the current frame, then do funcall.  */
1679_spentry(tcallsymslide)
1680        __(ldr lr,[sp,#lisp_frame.savelr])
1681        __(ldr fn,[sp,#lisp_frame.savefn])
1682        __(ldr imm0,[sp,#lisp_frame.savevsp])
1683        __(discard_lisp_frame())
1684        /* can use nfn (= temp2) as a temporary  */
1685        __(sub imm1,nargs,#nargregs<<fixnumshift)
1686        __(add imm1,imm1,vsp)
16871:
1688        __(ldr temp2,[imm1,#-node_size]!)
1689        __(cmp imm1,vsp)
1690        __(push1(temp2,imm0))
1691        __(bne 1b)
1692        __(mov vsp,imm0)
1693        __(jump_fname)
1694
1695
1696/* Tail-recursively call the function in nfn.  */
1697/* Pretty much the same as the tcallsym* cases above.  */
1698_spentry(tcallnfngen)
1699        __(cmp nargs,#nargregs<<fixnumshift)
1700        __(bgt _SPtcallnfnslide)
1701        __(restore_lisp_frame(imm0))
1702        __(jump_nfn())
1703         
1704/* Some args were vpushed.  Slide them down to the base of  */
1705/* the current frame, then do funcall.  */
1706_spentry(tcallnfnslide)
1707        __(ldr lr,[sp,#lisp_frame.savelr])
1708        __(ldr fn,[sp,#lisp_frame.savefn])
1709        __(ldr imm0,[sp,#lisp_frame.savevsp])
1710        __(discard_lisp_frame())
1711        /* Since we have a known function, can use fname as a temporary.  */
1712        __(sub imm1,nargs,#nargregs<<fixnumshift)
1713        __(add imm1,imm1,vsp)
17141:
1715        __(ldr fname,[imm1,#-node_size]!)
1716        __(cmp imm1,vsp)
1717        __(push1(fname,imm0))
1718        __(bne 1b)
1719        __(mov vsp,imm0)
1720        __(jump_nfn())
1721
1722
1723/* Reference index arg_z of a misc-tagged object (arg_y).  */
1724/* Note that this conses in some cases.  Return a properly-tagged  */
1725/* lisp object in arg_z.  Do type and bounds-checking.  */
1726
1727_spentry(misc_ref)
1728        __(trap_unless_fulltag_equal(arg_y,fulltag_misc,imm0))
1729        __(trap_unless_fixnum(arg_z))
1730        __(vector_length(imm0,arg_y,imm1))
1731        __(cmp arg_z,imm0)
1732        __(uuo_error_vector_bounds(hs,arg_z,arg_y))
1733        __(extract_lowbyte(imm1,imm1)) /* imm1 = subtag  */
1734        __(b C(misc_ref_common))
1735
1736/* like misc_ref, only the boxed subtag is in arg_x.  */
1737
1738_spentry(subtag_misc_ref)
1739        __(trap_unless_fulltag_equal(arg_y,fulltag_misc,imm0))
1740        __(trap_unless_fixnum(arg_z))
1741        __(vector_length(imm0,arg_y,imm1))
1742        __(cmp arg_z,imm0)
1743        __(uuo_error_vector_bounds(hs,arg_z,arg_y))
1744        __(unbox_fixnum(imm1,arg_x))
1745        __(b C(misc_ref_common))
1746
1747
1748/* Make a "raw" area on the temp stack, stack-cons a macptr to point to it,  */
1749/* and return the macptr.  Size (in bytes, boxed) is in arg_z on entry; macptr */
1750/* in arg_z on exit.  */
1751_spentry(makestackblock)
1752        __(unbox_fixnum(imm1,arg_z))
1753        __(dnode_align(imm1,imm1,0))
1754        __(add imm1,imm1,#node_size)
1755        __(add imm0,imm1,#node_size)
1756        __(cmp imm0,#stack_alloc_limit)
1757        __(mov temp0,sp)
1758        __(bhs 1f)
1759        __(mov imm1,imm1,lsl #num_subtag_bits)
1760        __(orr imm1,imm1,#subtag_u8_vector)
1761        __(stack_allocate_ivector(imm1,imm0))
1762        __(add temp1,sp,#dnode_size)
1763        __(movc16(imm1,make_header(macptr.element_count,subtag_macptr)))
1764        __(str imm1,[sp,#-macptr.size]!)
1765        __(add arg_z,sp,#fulltag_misc)
1766        __(str temp1,[arg_z,#macptr.address])
1767        __(mov imm0,#0)
1768        __(mov imm1,#stack_alloc_marker)
1769        __(str imm0,[arg_z,#macptr.type])
1770        __(str imm0,[arg_z,#macptr.domain])
1771        __(stmdb sp!,{imm1,temp0})
1772        __(bx lr)
1773
1774        /* Too big. Heap cons a gcable macptr  */
17751:
1776        __(mov imm1,#stack_alloc_marker)
1777        __(stmdb sp!,{imm1,temp0})
1778        __(set_nargs(1))
1779        __(ref_nrs_symbol(fname,new_gcable_ptr,imm0))
1780        __(jump_fname())
1781
1782/* As above, only set the block's contents to 0.  */
1783_spentry(makestackblock0)
1784        __(unbox_fixnum(imm1,arg_z))
1785        __(dnode_align(imm1,imm1,0))
1786        __(add imm1,imm1,#node_size)
1787        __(add imm0,imm1,#node_size)
1788        __(cmp imm0,#stack_alloc_limit)
1789        __(mov temp0,sp)
1790        __(bhs 1f)
1791        __(mov imm1,imm1,lsl #num_subtag_bits)
1792        __(orr imm1,imm1,#subtag_u8_vector)
1793        __(stack_allocate_ivector(imm1,imm0))
1794        __(add temp1,sp,#dnode_size)
1795        __(movc16(imm1,make_header(macptr.element_count,subtag_macptr)))
1796        __(str imm1,[sp,#-macptr.size]!)
1797        __(add arg_z,sp,#fulltag_misc)
1798        __(str temp1,[arg_z,#macptr.address])
1799        __(mov imm0,#0)
1800        __(mov imm1,#stack_alloc_marker)
1801        __(str imm0,[arg_z,#macptr.type])
1802        __(str imm0,[arg_z,#macptr.domain])
1803        __(stmdb sp!,{imm1,temp0})
1804        __(bx lr)
1805       
1806        /* Too big. Heap cons a gcable macptr  */
18071:
1808        __(mov imm1,#stack_alloc_marker)
1809        __(stmdb sp!,{imm1,temp0})
1810        __(mov arg_y,arg_z) /* save block size  */
1811        __(mov arg_z,#nil_value) /* clear-p arg to %new-gcable-ptr  */
1812        __(add arg_z,arg_z,#t_offset)
1813        __(set_nargs(2))
1814        __(ref_nrs_symbol(fname,new_gcable_ptr,imm0))
1815        __(jump_fname())
1816
1817/* Make a list of length arg_y (boxed), initial-element arg_z (boxed) on  */
1818/* the tstack.  Return the list in arg_z.  */
1819_spentry(makestacklist)
1820        __(add imm0,arg_y,arg_y)
1821        __(mov imm1,imm0,lsl #num_subtag_bits-fixnumshift)
1822        __(add imm1,imm1,#4<<num_subtag_bits)
1823        __(orr imm1,imm1,#subtag_u32_vector)
1824        __(add imm0,imm0,#dnode_size)
1825        __(cmp imm0,#stack_alloc_limit)
1826        __(bge 4f)
1827        __(stack_allocate_zeroed_ivector(imm1,imm0))
1828        __(mov imm0,#subtag_simple_vector)
1829        __(strb imm0,[sp,#0])
1830        __(add imm2,sp,#dnode_size+fulltag_cons)
1831        __(movs imm1,arg_y)
1832        __(mov arg_y,arg_z)
1833        __(mov arg_z,#nil_value)
1834        __(b 3f)
18352:
1836        __(_rplacd(imm2,arg_z))
1837        __(_rplaca(imm2,arg_y))
1838        __(mov arg_z,imm2)
1839        __(add imm2,imm2,#cons.size)
1840        __(subs imm1,imm1,#fixnumone)
18413:
1842        __(bne 2b)
1843        __(bx lr)
18444:
1845        __(movc16(imm0,make_header(1,subtag_u32_vector)))
1846        __(str imm0,[sp,#-8]!)
1847        __(movs imm1,arg_y) /* count  */
1848        __(mov arg_y,arg_z) /* initial value  */
1849        __(mov arg_z,#nil_value) /* result  */
1850        __(b 6f)
18515:
1852        __(Cons(arg_z,arg_y,arg_z))
1853        __(subs imm1,imm1,#fixnumone)
18546:
1855        __(bne 5b)
1856        __(bx lr)
1857
1858/* subtype (boxed) vpushed before initial values. (Had better be a  */
1859/* node header subtag.) Nargs set to count of things vpushed.  */
1860
1861_spentry(stkgvector)
1862        __(sub imm0,nargs,#fixnumone)
1863        __(ldr temp0,[vsp,imm0])
1864        __(dnode_align(temp1,imm0,node_size))
1865        __(mov imm1,imm0,lsl #num_subtag_bits-fixnumshift)
1866        __(orr imm1,imm1,#subtag_u32_vector)
1867        __(stack_allocate_zeroed_ivector(imm1,temp1))
1868        __(unbox_fixnum(imm1,temp0))
1869        __(strb imm1,[sp])
1870        __(add arg_z,sp,#fulltag_misc)
1871        __(add imm0,sp,nargs)
1872        __(b 2f)
18731:
1874        __(vpop1(temp0))
1875        __(push1(temp0,imm0))
18762:      __(subs nargs,nargs,#fixnumone)
1877        __(bne 1b)
1878        __(add vsp,vsp,#fixnumone)
1879        __(bx lr)
1880
1881/* Allocate a "fulltag_misc" object.  On entry, arg_y contains the element  */
1882/* count (boxed) and  arg_z contains the subtag (boxed).  Both of these   */
1883/* parameters must be "reasonable" (the  subtag must be valid, the element  */
1884/* count must be of type (unsigned-byte 24)/(unsigned-byte 56).   */
1885/* On exit, arg_z contains the (properly tagged) misc object; it'll have a  */
1886/* proper header on it and its contents will be 0.   imm0 contains   */
1887/* the object's header (fulltag = fulltag_immheader or fulltag_nodeheader.)  */
1888
1889_spentry(misc_alloc)
1890        __(tst arg_y,#unsigned_byte_24_mask)
1891        __(bne 9f)
1892        __(unbox_fixnum(imm0,arg_z))
1893        __(orr imm0,imm0,arg_y,lsl #num_subtag_bits-fixnumshift)
1894        __(extract_fulltag(imm1,imm0))
1895        __(cmp imm1,#fulltag_nodeheader)
1896        __(mov imm2,arg_y)      /* imm2 = logical size in bytes */
1897        __(beq 1f)
1898        __(unbox_fixnum(imm1,arg_z))
1899        __(cmp imm1,#max_32_bit_ivector_subtag)
1900        __(ble 1f)
1901        __(mov imm2,arg_y,lsr #2)
1902        __(cmp imm1,#max_8_bit_ivector_subtag)
1903        __(ble 1f)
1904        __(mov imm2,arg_y,lsr #1)
1905        __(cmp imm1,#max_16_bit_ivector_subtag)
1906        __(ble 1f)
1907        __(mov imm2,arg_y,lsl #1)
1908        __(add imm2,imm2,#node_size)
1909        __(cmp imm1,#subtag_double_float_vector)
1910        __(beq 1f)
1911        __(add imm2,arg_y,#7<<fixnumshift)
1912        __(mov imm2,imm2,lsr #3+fixnumshift)
1913        /* imm2 now = byte count.  Add 4 for header, 7 to align, then clear */
1914        /* low three bits.  */
19151:
1916        __(dnode_align(imm2,imm2,node_size))
1917        __(Misc_Alloc(arg_z,imm0,imm2))
1918        __(bx lr)
19199:
1920        __(uuo_error_reg_not_xtype(al,arg_y,xtype_unsigned_byte_24))
1921
1922
1923
1924
1925_spentry(unused0)
1926
1927_spentry(unused1)
1928
1929_spentry(unused2)
1930
1931dnl /* vpush the values in the value set atop the vsp, incrementing nargs.  */
1932dnl /* Discard the tsp frame; leave values atop the vsp.  */
1933dnl
1934_spentry(recover_values)
1935dnl
1936dnl /* First, walk the segments reversing the pointer to previous segment pointers  */
1937dnl /* Can tell the end because that previous segment pointer is the prev tsp pointer  */
1938dnl  __(ldr imm0,[tsp,#tsp_frame.backlink]) /* previous tsp  */
1939dnl  __(mov imm1,tsp) /* current segment  */
1940dnl  __(mov imm2,tsp) /* last segment  */
1941dnl local_label(walkloop):
1942dnl  __(ldr imm3,[imm1,#tsp_frame.fixed_overhead+node_size]) /* next segment  */
1943dnl  __(cmpr(imm0,imm3)) /* last segment?  */
1944dnl  __(str(imm2,tsp_frame.fixed_overhead+node_size(imm1))) /* reverse pointer  */
1945dnl  __(mov imm2,imm1) /* last segment <- current segment  */
1946dnl  __(mov imm1,imm3) /* current segment <- next segment  */
1947dnl  __(bne local_label(walkloop))
1948dnl
1949dnl         /* the final segment ptr is now in imm2  */
1950dnl         /* walk backwards, pushing values on VSP and incrementing NARGS  */
1951dnl local_label(pushloop):
1952dnl  __(ldr imm0,[imm2,#tsp_frame.data_offset]) /* nargs in segment  */
1953dnl  __(cmpri(imm0,0))
1954dnl  __(cmpr(cr1,imm2,tsp))
1955dnl  __(la imm3,tsp_frame.data_offset+(2*node_size)(imm2))
1956dnl  __(add imm3,imm3,imm0)
1957dnl  __(add nargs,nargs,imm0)
1958dnl  __(b 2f)
1959dnl 1:
1960dnl  __(ldru(arg_z,-node_size(imm3)))
1961dnl  __(cmpri(imm0,fixnum_one))
1962dnl  __(subi imm0,imm0,fixnum_one)
1963dnl  __(vpush1(arg_z))
1964dnl 2:
1965dnl  __(bne 1b)
1966dnl  __(ldr imm2,[imm2,#tsp_frame.data_offset+node_size]) /* previous segment  */
1967dnl  __(bne cr1,local_label(pushloop))
1968dnl  __(unlink(tsp))
1969dnl  __(bx lr)
1970
1971
1972
1973/* If arg_z is an integer, return in imm0 something whose sign  */
1974/* is the same as arg_z's.  If not an integer, error.  */
1975_spentry(integer_sign)
1976        __(test_fixnum(arg_z))
1977        __(moveq imm0,arg_z)
1978        __(bxeq lr)
1979        __(extract_typecode(imm0,arg_z))
1980        __(cmp imm0,#subtag_bignum)
1981        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_integer))
1982        __(getvheader(imm1,arg_z))
1983        __(header_length(imm0,imm1)) /* boxed length = scaled size  */
1984        __(add imm0,imm0,#misc_data_offset-4) /* bias, less 1 element  */
1985        __(ldr imm0,[arg_z,imm0])
1986        __(cmp imm0,#0)
1987        __(movge imm0,#1)
1988        __(movlt imm0,#-1)
1989        __(bx lr)
1990
1991
1992/* like misc_set, only pass the (boxed) subtag in temp0  */
1993_spentry(subtag_misc_set)
1994        __(trap_unless_fulltag_equal(arg_x,fulltag_misc,imm0))
1995        __(trap_unless_fixnum(arg_y))
1996        __(vector_length(imm0,arg_x,imm1))
1997        __(cmp arg_y,imm0)
1998        __(uuo_error_vector_bounds(hs,arg_y,arg_x))
1999        __(unbox_fixnum(imm1,temp0))
2000        __(b C(misc_set_common))
2001
2002
2003
2004/* misc_set (vector index newval).  Pretty damned similar to  */
2005/* misc_ref, as one might imagine.  */
2006
2007_spentry(misc_set)
2008        __(trap_unless_fulltag_equal(arg_x,fulltag_misc,imm0))
2009        __(trap_unless_fixnum(arg_y))
2010        __(vector_length(imm0,arg_x,imm1))
2011        __(cmp arg_y,imm0)
2012        __(uuo_error_vector_bounds(hs,arg_y,arg_x))
2013        __(extract_lowbyte(imm1,imm1))
2014        __(b C(misc_set_common))
2015
2016/* "spread" the lexpr in arg_z.  */
2017/* ppc2-invoke-fn assumes that temp1 is preserved here.  */
2018_spentry(spread_lexprz)
2019        __(ldr imm0,[arg_z,#0])
2020        __(add imm1,arg_z,imm0)
2021        __(add nargs,nargs,imm0)
2022        __(add imm1,imm1,#node_size)
2023        __(cmp imm0,#3<<fixnumshift)
2024        __(bge 9f)
2025        __(cmp imm0,#2<<fixnumshift)
2026        __(beq 2f)
2027        __(cmp imm0,#0)
2028        __(bne 1f)
2029/* lexpr count was 0; vpop the arg regs that  */
2030/* were vpushed by the caller  */
2031        __(cmp nargs,#0)
2032        __(bxeq lr)
2033        __(vpop_argregs_nz)
2034        __(bx lr)
2035
2036/* vpush args from the lexpr until we have only  */
2037/* three left, then assign them to arg_x, arg_y,  */
2038/* and arg_z.  */
20398:
2040        __(cmp imm0,#4<<fixnumshift)
2041        __(sub imm0,imm0,#fixnumone)
2042        __(ldr arg_z,[imm1,#-node_size]!)
2043        __(vpush1(arg_z))
20449:
2045        __(bne 8b)
2046        __(ldr arg_x,[imm1,#-node_size*1])
2047        __(ldr arg_y,[imm1,#-node_size*2])
2048        __(ldr arg_z,[imm1,#-node_size*3])
2049        __(bx lr)
2050
2051/* lexpr count is two: set arg_y, arg_z from the  */
2052/* lexpr, maybe vpop arg_x  */
20532:
2054        __(cmp nargs,#2<<fixnumshift)
2055        __(ldr arg_y,[imm1,#-node_size*1])
2056        __(ldr arg_z,[imm1,#-node_size*2])
2057        __(bxeq lr)  /* return if (new) nargs = 2  */
2058        __(vpop1(arg_x))
2059        __(bx lr)
2060
2061/* lexpr count is one: set arg_z from the lexpr,  */
2062/* maybe vpop arg_y, arg_x  */
20631:
2064        __(cmp nargs,#2<<fixnumshift)
2065        __(ldr arg_z,[imm1,#-node_size])
2066        __(bxlt lr)  /* return if (new) nargs < 2  */
2067        __(vpop1(arg_y))
2068        __(bxeq lr)  /* return if (new) nargs = 2  */
2069        __(vpop1(arg_x))
2070        __(bx lr)
2071
2072
2073_spentry(reset)
2074        __(nop)
2075        __(ref_nrs_value(temp0,toplcatch))
2076        __(mov temp1,#XSTKOVER)
2077        __(vpush1(temp0))
2078        __(vpush1(temp1))
2079        __(set_nargs(1))
2080        __(b _SPthrow)
2081
2082
2083/* "slide" nargs worth of values up the vstack.  IMM0 contains  */
2084/* the difference between the current VSP and the target.  */
2085_spentry(mvslide)
2086        __(cmp nargs,#0)
2087        __(mov temp1,nargs)
2088        __(add imm1,vsp,nargs)
2089        __(add imm1,imm1,imm0)
2090        __(add imm0,vsp,nargs)
2091        __(beq 2f)
20921:
2093        __(subs temp1,temp1,#1<<fixnumshift)
2094        __(ldr temp0,[imm0,#-node_size]!)
2095        __(str temp0,[imm1,#-node_size]!)
2096        __(bne 1b)
2097        2:
2098        __(mov vsp,imm1)
2099        __(bx lr)
2100
2101dnl /* Build a new TSP area to hold nargs worth of multiple-values.  */
2102dnl /* Pop the multiple values off of the vstack.  */
2103dnl /* The new TSP frame will look like this:  */
2104dnl /*  */
2105dnl /*+--------+-------+-------+---------+--------+--------+--------+======+----------+ */
2106dnl /*| ptr to | zero  | nargs | ptr to  | valn-1 | valn-2 | val-0  | ???? | prev TSP |  */
2107dnl /*|  prev  |       |       |  prev   |        |        |        | fill |          |  */
2108dnl /*| TSP    |       |       | segment |        |        |        |      |          | */
2109dnl /*+--------+-------+-------+---------+--------+--------+--------+------+----------+  */
2110dnl /*  */
2111dnl /* e.g., the first multiple value goes in the last cell in the frame, the  */
2112dnl /* count of values goes in the first word, and the word after the value count  */
2113dnl /* is 0 if the number of values is even (for alignment).  */
2114dnl /* Subsequent calls to .SPadd_values preserve this alignment.  */
2115dnl /* .SPrecover_values is therefore pretty simple.  */
2116dnl
2117_spentry(save_values)
2118dnl  __(mov imm1,tsp)
2119dnl
2120dnl         /* common exit: nargs = values in this set, imm1 = ptr to tsp before  */
2121dnl         /* call to save_values  */
2122dnl local_label(save_values_to_tsp):
2123dnl  __(mov imm2,tsp)
2124dnl  __(dnode_align(imm0,nargs,tsp_frame.fixed_overhead+(2*node_size))) /* count, link  */
2125dnl  __(TSP_Alloc_Var_Boxed_nz(imm0,imm3))
2126dnl  __(str(imm1,tsp_frame.backlink(tsp))) /* keep one tsp "frame" as far as rest of lisp is concerned  */
2127dnl  __(str(nargs,tsp_frame.data_offset(tsp)))
2128dnl  __(str(imm2,tsp_frame.data_offset+node_size(tsp))) /* previous tsp  */
2129dnl  __(la imm3,tsp_frame.data_offset+node_size*2(tsp))
2130dnl  __(add imm3,imm3,nargs)
2131dnl  __(add imm0,vsp,nargs)
2132dnl  __(cmpr(imm0,vsp))
2133dnl  __(b 2f)
2134dnl 1:
2135dnl  __(ldru(arg_z,-node_size(imm0)))
2136dnl  __(cmpr(imm0,vsp))
2137dnl  __(stru(arg_z,-node_size(imm3)))
2138dnl 2:
2139dnl  __(bne 1b)
2140dnl  __(add vsp,vsp,nargs) /*  discard values  */
2141dnl  __(bx lr)
2142dnl 
2143dnl
2144dnl /* Add the multiple values that are on top of the vstack to the set  */
2145dnl /* saved in the top tsp frame, popping them off of the vstack in the  */
2146dnl /* process.  It is an error (a bad one) if the TSP contains something  */
2147dnl /* other than a previously saved set of multiple-values.  */
2148dnl /* Since adding to the TSP may cause a new TSP segment to be allocated,  */
2149dnl /* each add_values call adds another linked element to the list of  */
2150dnl /* values. This makes recover_values harder.  */
2151dnl
2152_spentry(add_values)
2153dnl  __(cmpri(nargs,0))
2154dnl  __(ldr imm1,[tsp,#0])
2155dnl  __(bne local_label(save_values_to_tsp))
2156dnl  __(bx lr)
2157dnl         
2158
2159/* Like misc_alloc (a LOT like it, since it does most of the work), but takes  */
2160/* an initial-value arg in arg_z, element_count in arg_x, subtag in arg_y.  */
2161/* Calls out to %init-misc, which does the rest of the work.  */
2162
2163_spentry(misc_alloc_init)
2164        __(build_lisp_frame(imm0))
2165        __(mov fn,#0)
2166        __(mov temp2,arg_z)  /* initval  */
2167        __(mov arg_z,arg_y)  /* subtag  */
2168        __(mov arg_y,arg_x)  /* element-count  */
2169        __(bl _SPmisc_alloc)
2170        __(restore_lisp_frame(imm0))
2171        __(ref_nrs_symbol(fname,init_misc,imm0))
2172        __(set_nargs(2))
2173        __(mov arg_y,temp2)
2174        __(jump_fname())
2175
2176/* As in stack_misc_alloc above, only with a non-default initial-value.  */
2177/* The funny part here is that we build a lisp frame, then push a vector
2178/* on top of it.  Shuffle things around, carefully. */       
2179               
2180 
2181_spentry(stack_misc_alloc_init)
2182        __(build_lisp_frame(imm0))
2183        __(mov arg_x,sp)
2184        __(mov fn,#0)
2185        __(mov temp2,arg_z) /* initval  */
2186        __(mov arg_z,arg_y) /* subtag  */
2187        __(mov arg_y,arg_x) /* element-count  */
2188        __(bl _SPstack_misc_alloc)
2189        __(mov imm0,#0)
2190        __(ldr lr,[arg_x,#lisp_frame.savelr])
2191        __(ldr fn,[arg_x,#lisp_frame.savefn])
2192        __(ldr vsp,[arg_x,#lisp_frame.savevsp])
2193        __(ldr imm1,[sp])
2194        __(add imm2,imm1,#lisp_frame.size)
2195        __(str imm2,[sp])
2196        __(str imm0,[arg_x,#lisp_frame.savelr])
2197        __(str imm0,[arg_x,#lisp_frame.savefn])
2198        __(str imm0,[arg_x,#lisp_frame.savevsp])
2199        __(str imm0,[arg_x,#lisp_frame.marker])
2200        __(str imm1,[sp,#lisp_frame.size]!)
2201        __(add arg_z,arg_z,#lisp_frame.size)
2202        __(ref_nrs_symbol(fname,init_misc,imm0))
2203        __(set_nargs(2))
2204        __(mov arg_y,temp2)
2205        __(jump_fname())
2206 
2207_spentry(popj)
2208        .globl C(popj)
2209C(popj):
2210        __(return_lisp_frame(imm0))
2211
2212
2213dnl
2214dnl         
2215dnl /* Nargs is valid; all arg regs, lexpr-count pushed by caller.  */
2216dnl /* imm0 = vsp to restore.  */
2217dnl /* Return all values returned by caller to its caller, hiding  */
2218dnl /* the variable-length arglist.  */
2219dnl /* If we can detect that the caller's caller didn't expect  */
2220dnl /* multiple values, then things are even simpler.  */
2221_spentry(lexpr_entry)
2222dnl  __(ref_global(imm1,ret1valn))
2223dnl  __(cmpr(imm1,loc_pc))
2224dnl  __(build_lisp_frame(fn,loc_pc,imm0))
2225dnl  __(bne 1f)
2226dnl  __(ref_global(imm0,lexpr_return))
2227dnl  __(build_lisp_frame(rzero,imm0,vsp))
2228dnl  __(mov loc_pc,imm1)
2229dnl  __(ldr imm0,[rcontext,#tcr.cs_limit])
2230dnl  __(trllt(sp,imm0))
2231dnl  __(mov fn,#0)
2232dnl  __(bx lr)
2233dnl
2234dnl         /* The single-value case just needs to return to something that'll pop  */
2235dnl         /* the variable-length frame off of the vstack.  */
2236dnl 1:
2237dnl  __(ref_global(loc_pc,lexpr_return1v))
2238dnl  __(ldr imm0,[rcontext,#tcr.cs_limit])
2239dnl  __(trllt(sp,imm0))
2240dnl  __(mov fn,#0)
2241dnl  __(bx lr)
2242
2243
2244
2245/* arg_z should be of type (UNSIGNED-BYTE 64);  */
2246/* return high 32 bits in imm1, low 32 bits in imm0 */
2247
2248
2249_spentry(getu64)
2250        __(test_fixnum(arg_z))
2251        __(bne 1f)
2252        __(unbox_fixnum(imm0,arg_z))
2253        __(movs imm1,imm0,asr #31)
2254        __(bxeq lr)
22550:             
2256        __(uuo_error_reg_not_xtype(al,arg_z,xtype_u64))
22571:
2258        __(extract_typecode(imm0,arg_z))
2259        __(cmp imm0,#subtag_bignum)
2260        __(bne 0b)
2261        __(movc16(imm1,two_digit_bignum_header))
2262        __(getvheader(imm0,arg_z))
2263        __(cmp imm0,imm1)
2264        __(bne 2f)
2265        __(vrefr(imm0,arg_z,0))
2266        __(vrefr(imm1,arg_z,1))
2267        __(cmp imm1,#0)
2268        __(bxge lr)
2269        __(uuo_error_reg_not_xtype(al,arg_z,xtype_u64))
22702:      __(movc16(imm1,three_digit_bignum_header))
2271        __(cmp imm0,imm1)
2272        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u64))
2273        __(vrefr(imm2,arg_z,2))
2274        __(cmp imm2,#0)
2275        __(vrefr(imm1,arg_z,1))
2276        __(vrefr(imm0,arg_z,0))
2277        __(bxeq lr)
2278        __(uuo_error_reg_not_xtype(al,arg_z,xtype_u64))
2279
2280         
2281/* arg_z should be of type (SIGNED-BYTE 64);  */
2282/*    return high 32 bits  in imm1, low 32 bits in imm0  */
2283
2284_spentry(gets64)
2285        __(test_fixnum(arg_z))
2286        __(moveq imm0,arg_z,asr #fixnumshift)
2287        __(moveq imm1,imm0,asr #31)
2288        __(bxeq lr)
2289        __(mov imm2,#0)
2290        __(extract_lisptag(imm0,arg_z))
2291        __(cmp imm0,#tag_misc)
2292        __(ldreq imm2,[arg_z,#misc_header_offset])
2293        __(movc16(imm1,two_digit_bignum_header))
2294        __(cmp imm1,imm2)
2295        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_s64))
2296        __(vrefr(imm1,arg_z,1))
2297        __(vrefr(imm0,arg_z,0))
2298        __(bx lr)
2299
2300
2301/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
2302/* unbound_marker), arg_y = symbol, imm1 = symbol.binding-index  */
2303_spentry(specref)
2304        __(ldr imm1,[arg_z,#symbol.binding_index])
2305        __(ldr imm0,[rcontext,#tcr.tlb_limit])
2306        __(cmp imm1,imm0)
2307        __(ldr temp0,[rcontext,#tcr.tlb_pointer])
2308        __(mov arg_y,arg_z)
2309        __(movhs imm1,#0)
2310        __(ldr arg_z,[temp0,imm1])
2311        __(cmp arg_z,#no_thread_local_binding_marker)
2312        __(ldreq arg_z,[arg_y,#symbol.vcell])
2313        __(bx lr)
2314
2315_spentry(specrefcheck)
2316        __(ldr imm1,[arg_z,#symbol.binding_index])
2317        __(ldr imm0,[rcontext,#tcr.tlb_limit])
2318        __(cmp imm1,imm0)
2319        __(movhs imm1,#0)
2320        __(ldr imm0,[rcontext,#tcr.tlb_pointer])
2321        __(mov arg_y,arg_z)
2322        __(ldr arg_z,[imm0,imm1])
2323        __(cmp arg_z,#no_thread_local_binding_marker)
2324        __(ldreq arg_z,[arg_y,#symbol.vcell])
2325        __(cmp arg_z,#unbound_marker)
2326        __(uuo_error_unbound(eq,arg_y))
2327        __(bx lr)
2328
2329/* arg_y = special symbol, arg_z = new value.          */
2330_spentry(specset)
2331        __(ldr imm1,[arg_y,#symbol.binding_index])
2332        __(ldr imm0,[rcontext,#tcr.tlb_limit])
2333        __(ldr imm2,[rcontext,#tcr.tlb_pointer])
2334        __(cmp imm1,imm0)
2335        __(movge imm1,#0)
2336        __(ldr temp1,[imm2,imm1])
2337        __(cmp temp1,#no_thread_local_binding_marker)
2338        __(strne arg_z,[imm2,imm1])
2339        __(bxne lr)
2340        __(mov arg_x,arg_y)
2341        __(mov arg_y,#symbol.vcell-misc_data_offset)
2342        __(b _SPgvset)
2343
2344
2345       
2346/* Construct a lisp integer out of the 32-bit signed value in imm0 */
2347/* arg_z should be of type (SIGNED-BYTE 32); return unboxed result in imm0 */
2348
2349_spentry(gets32)
2350        __(test_fixnum(arg_z))
2351        __(moveq imm0,arg_z,asr #fixnumshift)
2352        __(bxeq lr)
2353        __(extract_lisptag(imm0,arg_z))
2354        __(cmp imm0,#tag_misc)
2355        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_s32))
2356        __(getvheader(imm0,arg_z))
2357        __(movc16(imm1,one_digit_bignum_header))
2358        __(cmp imm0,imm1)
2359        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_s32))
2360        __(vrefr(imm0,arg_z,0))
2361        __(bx lr)       
2362
2363
2364/*  */
2365/* arg_z should be of type (UNSIGNED-BYTE 32); return unboxed result in imm0 */
2366/*  */
2367
2368_spentry(getu32)
2369        __(test_fixnum(arg_z))
2370        __(moveq imm0,arg_z,asr #fixnumshift)
2371        __(movseq imm1,imm0,asr #31)
2372        __(bxeq lr)
2373        __(movc16(imm1,one_digit_bignum_header))
2374        __(extract_lisptag(imm0,arg_z))
2375        __(cmp imm0,#tag_misc)
2376        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u32))
2377        __(getvheader(imm0,arg_z))
2378        __(cmp imm0,imm1)
2379        __(ldreq imm0,[arg_z,#misc_data_offset])
2380        __(beq 7f)
2381        __(movc16(imm1,two_digit_bignum_header))
2382        __(cmp imm0,imm1)
2383        __(ldreq imm0,[arg_z,#misc_data_offset])
2384        __(ldreq imm1,[arg_z,#misc_data_offset+4])
2385        __(cmpeq imm1,#0)
2386        __(bxeq lr)
2387        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u32))
23887:             
2389        __(movs imm1,imm0,asr #31)
2390        __(bxeq lr)
2391        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u32))
2392
2393
2394/* */
2395/* As per mvpass above, but in this case fname is known to be a */
2396/* symbol. */
2397
2398_spentry(mvpasssym)
2399        __(cmp nargs,#node_size*nargregs)
2400        __(mov nfn,vsp)
2401        __(subgt nfn,nfn,#node_size*nargregs)
2402        __(addgt nfn,nfn,nargs)
2403        __(build_lisp_frame(imm0,nfn))
2404        __(ref_global(lr,ret1val_addr,imm0))
2405        __(mov fn,#0)
2406        __(jump_fname())
2407
2408_spentry(unbind)
2409        __(ldr imm1,[rcontext,#tcr.db_link])
2410        __(ldr temp0,[rcontext,#tcr.tlb_pointer])   
2411        __(ldr imm0,[imm1,#binding.sym])
2412        __(ldr temp1,[imm1,#binding.val])
2413        __(ldr imm1,[imm1,#binding.link])
2414        __(str temp1,[temp0,imm0])
2415        __(str imm1,[rcontext,#tcr.db_link])
2416        __(bx lr)
2417
2418/* Clobbers imm1,temp0,arg_x, arg_y */       
2419_spentry(unbind_n)
2420        __(ldr imm1,[rcontext,#tcr.db_link])
2421        __(ldr arg_x,[rcontext,#tcr.tlb_pointer])
24221:      __(ldr temp0,[imm1,#binding.sym])
2423        __(ldr arg_y,[imm1,#binding.val])
2424        __(ldr imm1,[imm1,#binding.link])
2425        __(subs imm0,imm0,#1)
2426        __(str arg_y,[arg_x,temp0])
2427        __(bne 1b)
2428        __(str imm1,[rcontext,#tcr.db_link])
2429        __(bx lr)
2430
2431/* */
2432/* Clobbers imm1,temp0,arg_x, arg_y */
2433
2434_spentry(unbind_to)
2435        do_unbind_to(imm1,temp1,arg_x,arg_y)
2436        __(bx lr)
2437 
2438
2439 
2440/* */
2441/* Restore the special bindings from the top of the tstack,  */
2442/* leaving the tstack frame allocated.  */
2443/* Note that there might be 0 saved bindings, in which case  */
2444/* do nothing.  */
2445/* Note also that this is -only- called from an unwind-protect  */
2446/* cleanup form, and that .SPnthrowXXX is keeping one or more  */
2447/* values in a frame on top of the tstack.  */
2448/*  */
2449                         
2450_spentry(progvrestore)
2451        __(skip_stack_vector(imm0,imm1,sp))
2452        /* There might be a lisp_frame at imm0.  Not sure */
2453        __(ldr imm0,[imm0,#node_size]) /* or maybe node_size+lisp_frame.size */
2454        __(cmp imm0,#0)
2455        __(unbox_fixnum(imm0,imm0))
2456        __(bne _SPunbind_n)
2457        __(bx lr)
2458
2459/* Bind CCL::*INTERRUPT-LEVEL* to 0.  If its value had been negative, check  */
2460/* for pending interrupts after doing so.  */
2461_spentry(bind_interrupt_level_0)
2462        __(ldr temp1,[rcontext,#tcr.tlb_pointer])
2463        __(ldr temp0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2464        __(ldr imm0,[rcontext,#tcr.db_link])
2465        __(cmp temp0,#0)
2466        __(mov imm1,#INTERRUPT_LEVEL_BINDING_INDEX)
2467        __(vpush1(temp0))
2468        __(vpush1(imm1))
2469        __(vpush1(imm0))
2470        __(mov imm0,#0)
2471        __(str imm0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2472        __(str vsp,[rcontext,#tcr.db_link])
2473        __(bxeq lr)
2474        __(ldrlt temp0,[rcontext,#tcr.interrupt_pending])
2475        __(cmp temp0,#0)
2476        __(uuo_interrupt_now(gt))
2477        __(bx lr)
2478       
2479/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect */
2480/* of disabling interrupts.)  */
2481_spentry(bind_interrupt_level_m1)
2482        __(mov imm2,#-fixnumone)
2483        __(mov imm1,#INTERRUPT_LEVEL_BINDING_INDEX)
2484        __(ldr temp1,[rcontext,#tcr.tlb_pointer])
2485        __(ldr temp0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2486        __(ldr imm0,[rcontext,#tcr.db_link])
2487        __(vpush1(temp0))
2488        __(vpush1(imm1))
2489        __(vpush1(imm0))
2490        __(str imm2,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2491        __(str vsp,[rcontext,tcr.db_link])
2492        __(bx lr)
2493       
2494
2495/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
2496/* do what _SPbind_interrupt_level_0 does  */
2497_spentry(bind_interrupt_level)
2498        __(cmp arg_z,#0)
2499        __(mov imm1,#INTERRUPT_LEVEL_BINDING_INDEX)
2500        __(ldr temp1,[rcontext,#tcr.tlb_pointer])
2501        __(ldr temp0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2502        __(ldr imm0,[rcontext,#tcr.db_link])
2503        __(beq _SPbind_interrupt_level_0)
2504        __(vpush1(temp0))
2505        __(vpush1(imm1))
2506        __(vpush1(imm0))
2507        __(str arg_z,[temp1,INTERRUPT_LEVEL_BINDING_INDEX])
2508        __(str vsp,[rcontext,#tcr.db_link])
2509        __(bx lr)
2510
2511/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
2512/* non-negative, check for pending interrupts.  This is often called in */
2513/* a context where nargs is significant, so save and restore nargs around */
2514/* any interrupt polling  */
2515         
2516_spentry(unbind_interrupt_level)
2517        __(ldr imm0,[rcontext,#tcr.flags])
2518        __(ldr temp2,[rcontext,#tcr.tlb_pointer])
2519        __(tst imm0,#1<<TCR_FLAG_BIT_PENDING_SUSPEND)
2520        __(ldr imm0,[rcontext,#tcr.db_link])
2521        __(ldr temp0,[temp2,#INTERRUPT_LEVEL_BINDING_INDEX])
2522        __(bne 5f)
25230:     
2524        __(ldr temp1,[imm0,#binding.val])
2525        __(ldr imm0,[imm0,#binding.link])
2526        __(str temp1,[temp2,#INTERRUPT_LEVEL_BINDING_INDEX])
2527        __(str imm0,[rcontext,#tcr.db_link])
2528        __(cmp temp0,#0)
2529        __(bxge lr)
2530        __(cmp temp1,#0)
2531        __(bxlt lr)
2532        __(check_enabled_pending_interrupt(imm0))
2533        __(bx lr)
25345:       /* Missed a suspend request; force suspend now if we're restoring
2535          interrupt level to -1 or greater */
2536        __(cmp temp0,#-2<<fixnumshift)
2537        __(bne 0b)
2538        __(ldr imm0,[imm1,#binding.val])
2539        __(cmp imm0,temp0)
2540        __(beq 0b)
2541        __(mov imm0,#1<<fixnumshift)
2542        __(str imm0,[temp2,INTERRUPT_LEVEL_BINDING_INDEX])
2543        __(suspend_now())
2544        __(b 0b)
2545 
2546 
2547/* arg_x = array, arg_y = i, arg_z = j. Typecheck everything.
2548    We don't know whether the array is alleged to be simple or
2549   not, and don't know anythng about the element type.  */
2550_spentry(aref2)
2551        __(trap_unless_fixnum(arg_y))
2552        __(trap_unless_fixnum(arg_z))
2553        __(extract_typecode(imm2,arg_x))
2554        __(cmp imm2,#subtag_arrayH)
2555        __(ldreq imm1,[arg_x,#arrayH.rank])
2556        __(cmpeq imm1,#2<<fixnumshift)
2557        __(uuo_error_reg_not_xtype(ne,arg_x,xtype_array2d))
2558        /* It's a 2-dimensional array.  Check bounds */
2559        __(ldr imm0,[arg_x,#arrayH.dim0])
2560        __(cmp arg_y,imm0)
2561        __(uuo_error_array_bounds(hs,arg_y,arg_x))
2562        __(ldr imm0,[arg_x,#arrayH.dim0+node_size])
2563        __(cmp arg_z,imm0)
2564        __(uuo_error_array_bounds(hs,arg_z,arg_x))
2565        __(unbox_fixnum(imm0,imm0))
2566        __(mul temp0,arg_y,imm0) /* no MLA on ARMv5 */
2567        __(add arg_z,arg_z,temp0)
2568        /* arg_z is now row-major-index; get data vector and
2569           add in possible offset */
2570        __(mov arg_y,arg_x)
25710:      __(ldr imm0,[arg_y,#arrayH.displacement])
2572        __(ldr arg_y,[arg_y,#arrayH.data_vector])
2573        __(extract_subtag(imm1,arg_y))
2574        __(cmp imm1,#subtag_vectorH)
2575        __(add arg_z,arg_z,imm0)
2576        __(bgt C(misc_ref_common))
2577        __(b 0b)
2578 
2579/* temp0 = array, arg_x = i, arg_y = j, arg_z = k */
2580_spentry(aref3)
2581        __(trap_unless_fixnum(arg_x))
2582        __(trap_unless_fixnum(arg_y))
2583        __(trap_unless_fixnum(arg_z))
2584        __(extract_typecode(imm2,temp0))
2585        __(mov imm1,#0)
2586        __(cmp imm2,#subtag_arrayH)
2587        __(ldreq imm1,[temp0,#arrayH.rank])
2588        __(cmp imm1,#3<<fixnumshift)
2589        __(uuo_error_reg_not_xtype(ne,temp0,xtype_array3d))
2590        /* It's a 3-dimensional array.  Check bounds */
2591        __(ldr imm2,[temp0,arrayH.dim0+(node_size*2)])
2592        __(ldr imm1,[temp0,#arrayH.dim0+node_size])
2593        __(ldr imm0,[temp0,#arrayH.dim0])
2594        __(cmp arg_z,imm2)
2595        __(uuo_error_array_bounds(hs,arg_z,temp0))
2596        __(cmp arg_y,imm1)
2597        __(uuo_error_array_bounds(hs,arg_y,temp0))
2598        __(cmp arg_x,imm0)
2599        __(uuo_error_array_bounds(hs,arg_x,temp0))
2600        __(unbox_fixnum(imm2,imm2))
2601        __(unbox_fixnum(imm1,imm1))
2602        __(mul arg_y,imm2,arg_y)
2603        __(mul imm1,imm2,imm1)
2604        __(mul arg_x,imm1,arg_x)
2605        __(add arg_z,arg_z,arg_y)
2606        __(add arg_z,arg_z,arg_x)
2607        __(mov arg_y,temp0)
26080:      __(ldr arg_x,[arg_y,#arrayH.displacement])
2609        __(ldr arg_y,[arg_y,#arrayH.data_vector])
2610        __(extract_subtag(imm1,arg_y))
2611        __(cmp imm1,#subtag_vectorH)
2612        __(add arg_z,arg_x,arg_z)
2613        __(bgt C(misc_ref_common))
2614        __(b 0b)
2615
2616
2617
2618
2619/* As for aref2 above, but temp = array, arg_x = i, arg_y = j, arg_z = newval */
2620_spentry(aset2)
2621        __(extract_typecode(imm0,temp0))
2622        __(cmp imm0,#subtag_arrayH)
2623        __(ldreq imm0,[temp0,#arrayH.rank])
2624        __(cmpeq imm0,#2<<fixnumshift)
2625        __(uuo_error_reg_not_xtype(ne,temp0,xtype_array2d))
2626        __(trap_unless_fixnum(arg_x))
2627        __(trap_unless_fixnum(arg_y))
2628        /* It's a 2-dimensional array.  Check bounds */
2629        __(ldr imm0,[temp0,#arrayH.dim0])
2630        __(cmp arg_x,imm0)
2631        __(uuo_error_array_bounds(hs,arg_x,temp0))
2632        __(ldr imm0,[temp0,#arrayH.dim0+node_size])
2633        __(cmp arg_y,imm0)
2634        __(uuo_error_array_bounds(hs,arg_y,temp0))
2635        __(unbox_fixnum(imm0,imm0))
2636        __(mul temp1,arg_x,imm0)
2637        __(add arg_y,arg_y,temp1)
2638        /* arg_y is now row-major-index; get data vector and
2639           add in possible offset */
2640        __(mov arg_x,temp0)
26410:      __(ldr imm0,[arg_x,#arrayH.displacement])
2642        __(ldr arg_x,[arg_x,#arrayH.data_vector])
2643        __(extract_subtag(imm1,arg_x))
2644        __(cmp imm1,#subtag_vectorH)
2645        __(add arg_y,arg_y,imm0)
2646        __(bgt C(misc_set_common))
2647        __(b 0b)
2648
2649                 
2650/* temp1 = array, temp0 = i, arg_x = j, arg_y = k, arg_z = new */       
2651_spentry(aset3)
2652        __(extract_typecode(imm0,temp1))
2653        __(cmp imm0,#subtag_arrayH)
2654        __(ldreq imm0,[temp1,#arrayH.rank])
2655        __(cmpeq imm0,#3<<fixnumshift)
2656        __(uuo_error_reg_not_xtype(ne,temp1,xtype_array3d))
2657        __(trap_unless_fixnum(temp0))
2658        __(trap_unless_fixnum(arg_x))
2659        __(trap_unless_fixnum(arg_y))
2660        /* It's a 3-dimensional array.  Check bounds */
2661        __(ldr imm2,[temp1,#arrayH.dim0+(node_size*2)])
2662        __(ldr imm1,[temp1,#arrayH.dim0+node_size])
2663        __(ldr imm0,[temp1,#arrayH.dim0])
2664        __(cmp arg_y,imm2)
2665        __(uuo_error_array_bounds(hs,arg_y,temp1))
2666        __(cmp arg_x,imm1)
2667        __(uuo_error_array_bounds(hs,arg_x,temp1))
2668        __(unbox_fixnum(imm1,imm1))
2669        __(cmp temp0,imm0)
2670        __(uuo_error_array_bounds(hs,temp0,temp1))
2671        __(mul arg_x,imm2,arg_x)
2672        __(mul imm1,imm2,imm1)
2673        __(mul temp0,imm1,temp0)
2674        __(add arg_y,arg_y,arg_x)
2675        __(add arg_y,arg_y,temp0)
2676        __(mov arg_x,temp1)
26770:      __(ldr temp0,[arg_x,#arrayH.displacement])
2678        __(ldr arg_x,[arg_x,#arrayH.data_vector])
2679        __(extract_subtag(imm1,arg_x))
2680        __(cmp imm1,#subtag_vectorH)
2681        __(add arg_y,arg_y,temp0)
2682        __(bgt C(misc_set_common))
2683        __(b 0b)
2684
2685
2686/* Treat the last (- nargs imm0) values on the vstack as keyword/value  */
2687/* pairs.  There'll be arg_z keyword arguments.  arg_y contains flags  */
2688/* that indicate whether &allow-other-keys was specified and whether  */
2689/* or not to leave the keyword/value pairs on the vstack for an &rest  */
2690/* argument.  Element 2 of the function in fn contains a vector of keyword.  */
2691/* If the number of arguments is greater than imm0, the difference must  */
2692/* be even.  */
2693/* All arg regs have been vpushed and the calling function has built a */
2694/* stack frame.  next_method_context must be preserved, as must the incoming */
2695/* key/value pairs and their number if we're going to make an &rest arg. */
2696           
2697
2698define(`keyword_flags',`arg_y')
2699define(`key_value_count',`arg_z')
2700
2701define(`keyword_flag_allow_other_keys',`(1<<fixnumshift)')
2702define(`keyword_flag_seen_allow_other_keys',`(2<<fixnumshift)')
2703define(`keyword_flag_unknown_keyword_seen',`(3<<fixnumshift)')
2704define(`keyword_flag_rest',`(4<<fixnumshift)')
2705
2706_spentry(keyword_bind)
2707        new_local_labels()       
2708        __(subs key_value_count,nargs,imm0)
2709        __(movmi key_value_count,#0)
2710        __(tst key_value_count,#fixnumone)
2711        __(bne local_label(odd_keywords))
2712        __(mov imm1,key_value_count,lsl #num_subtag_bits-fixnumshift)
2713        __(orr imm1,imm1,subtag_u32_vector)
2714        __(add imm0,key_value_count,#dnode_size) /* we know  count is even */
2715        __(stack_allocate_zeroed_ivector(imm1,imm0))
2716        __(mov imm0,#subtag_simple_vector)
2717        __(strb imm0,[sp])
2718        /* Copy key/value pairs in reverse order from the vstack to
2719           the gvector we just created on the cstack. */
2720        __(add imm0,vsp,key_value_count) /* src, predecrement */
2721        __(add imm1,sp,#node_size)       /* dest, postincrement */
2722        __(mov temp2,key_value_count)
2723        __(b 1f)
27240:      __(ldr arg_x,[imm0,#-node_size]!)
2725        __(str arg_x,[imm1],#node_size)
27261:      __(subs temp2,temp2,#fixnumone)
2727        __(bge 0b)
2728        /* Discard the key/value pairs from the vstack. */
2729        __(add vsp,vsp,key_value_count)
2730        __(ldr temp2,[fn,#misc_data_offset+(2*node_size)])
2731        __(getvheader(imm0,temp2))
2732        __(mov imm0,imm0,lsr #num_subtag_bits)
2733        __(mov temp0,vsp)
2734        __(mov imm1,#nil_value)
2735        /* Push a pair of NILs (value, supplied-p) for each defined keyword */
2736        __(b 3f)
27372:      __(vpush1(imm1))
2738        __(vpush1(imm1))
27393:      __(subs imm0,imm0,#1)
2740        __(bge 2b)
2741        /* Save nargs and temp1 so that we can use them in the loop(s) */
2742        __(stmdb vsp!,{imm2,temp1})
2743        /* For each provided key/value pair: if the key is :allow-other-keys
2744           and that hasn't been seen before, note that it's been seen and
2745           if the value is non-nil set the allow-other-keys bit in flags.
2746           Then search for the key in the defined keys vector.  If it's
2747           not found, note that an undefined keyword was seen by setting
2748           a bit in keyword_flags ; if it is found, use its position to
2749           index the table of value/supplied-p pairs that we pushed above.
2750           If the supplied-p var is already set, do nothing; otherwise,
2751           set the supplied-p var and value.
2752           When done, signal an error if we got an unknown keyword, or
2753           either copy the supplied key/value pairs back to the vstack
2754           if we're going to cons an &rest arg or discard them if we aren't.
2755        */
2756        __(mov imm2,#0)
2757        __(b local_label(nextvalpairtest))
2758local_label(nextvalpairloop):   
2759        __(add temp1,sp,#4)
2760        __(ldr temp1,[temp1,imm2])
2761        __(ref_nrs_symbol(imm1,kallowotherkeys,imm1))
2762        __(cmp temp1,imm1)
2763        __(tsteq keyword_flags,#keyword_flag_seen_allow_other_keys)
2764        __(bne local_label(current_key_allow_other_keys_handled))
2765        __(orr keyword_flags,keyword_flags,#keyword_flag_seen_allow_other_keys)
2766        /* Fortunately, we know what the keyword is.  Need to check the
2767           value here, and don't have a lot of free registers ... */
2768        __(add temp1,sp,#8)
2769        __(ldr temp1,[temp1,imm2])
2770        __(cmp temp1,#nil_value)
2771        __(orrne keyword_flags,keyword_flags,#keyword_flag_allow_other_keys)
2772        __(mov temp1,imm1)      /* from comparison above */
2773local_label(current_key_allow_other_keys_handled):
2774        __(getvheader(imm0,temp1))
2775        __(header_length(arg_x,imm0))
2776        __(add imm0,arg_x,#misc_data_offset)
2777        __(b local_label(defined_keyword_compare_test))
2778local_label(defined_keyword_compare_loop):     
2779        __(ldr arg_x,[temp2,imm0])
2780        __(cmp arg_x,temp1)
2781        __(subeq imm0,imm0,#misc_data_offset)
2782        __(beq local_label(defined_keyword_found))
2783local_label(defined_keyword_compare_test):     
2784        __(sub imm0,imm0,#node_size)
2785        __(cmp imm0,#misc_data_offset)
2786        __(bge local_label(defined_keyword_compare_loop))
2787        /* keyword wasn't defined.  Note that ... */
2788        __(orr keyword_flags,keyword_flags,#keyword_flag_unknown_keyword_seen)
2789        __(b local_label(nextkeyvalpairnext))
2790local_label(defined_keyword_found):     
2791        __(sub imm0,temp0,imm0,lsl #1)
2792        __(ldr arg_x,[imm0,#-8])
2793        __(cmp arg_x,#nil_value) /* seen this keyword yet ? */
2794        __(bne local_label(nextkeyvalpairnext))
2795        __(add arg_x,arg_x,#t_offset)
2796        __(str arg_x,[imm0,#-8])
2797        __(add temp1,sp,#8)
2798        __(ldr temp1,[temp1,imm2])
2799        __(str temp1,[imm0,#-4])
2800local_label(nextkeyvalpairnext):
2801        __(add imm2,imm2,#8)
2802local_label(nextvalpairtest):   
2803        __(cmp imm2,key_value_count)
2804        __(bne local_label(nextvalpairloop))
2805        __(ldmia vsp!,{imm2,temp1})
2806        /* If unknown keywords and that's not allowed, signal error.
2807           Otherwise, discard the stack-consed vector and return,
2808           possibly after having copied the vector's contents back
2809           to the vstack so that an &rest arg can be constructed.
2810        */
2811        __(tst keyword_flags,#keyword_flag_unknown_keyword_seen)
2812        __(beq 0f)
2813        __(tst keyword_flags,#keyword_flag_allow_other_keys)
2814        __(beq local_label(badkeys))
28150:      __(tst keyword_flags,#keyword_flag_rest)
2816        __(beq local_label(discard_stack_vector))
2817        __(mov nargs,#0)
2818        __(add temp2,sp,#node_size)
2819        __(b 2f)
28201:      __(ldr arg_x,[temp2],#node_size)
2821        __(vpush1(arg_x))
2822        __(add nargs,nargs,#fixnumone)
28232:      __(cmp nargs,key_value_count)
2824        __(bne 1b)
2825local_label(discard_stack_vector):     
2826        __(add key_value_count,key_value_count,#dnode_size)
2827        __(add sp,sp,key_value_count)
2828        __(bx lr)               /* it's finally over ! */
2829
2830local_label(badkeys):   /* Disturbingly similar to the &rest case */
2831        __(mov nargs,#0)
2832        __(add temp2,sp,#node_size)
2833        __(mov vsp,temp0)
2834        __(b 1f)
28350:      __(ldr arg_x,[temp2],#node_size)
2836        __(vpush1(arg_x))
2837        __(add nargs,nargs,#fixnumone)
28381:      __(cmp nargs,key_value_count)
2839        __(bne 0b)
2840        /* Lose the stack vector */
2841        __(add key_value_count,key_value_count,#dnode_size)
2842        __(add sp,sp,key_value_count)
2843local_label(error_exit):               
2844        __(bl _SPconslist)
2845        __(mov arg_y,#XBADKEYS)
2846        __(set_nargs(2))
2847        __(b _SPksignalerr)
2848local_label(odd_keywords):       
2849        __(mov nargs,key_value_count)
2850        __(b local_label(error_exit))
2851
2852/* Most ARMs don't have hardware integer division.  This algorithm's
2853  from Sloss, Symes, & Wright.  On entry: imm0 = numerator, imm1 = denominator;
2854  on exit, imm0 = quotient, imm1 = remainder, imm2 clobbered.  Check for /0
2855  here, so that callers don't have to.
2856*/       
2857_spentry(udiv32)
2858        __(cmp imm0,#0)
2859        __(moveq arg_z,#XDIVZRO)
2860        __(moveq nargs,#1<<fixnumshift)
2861        __(beq _SPksignalerr)
2862        __(ldr imm2,[rcontext,#tcr.flags])
2863        __(orr imm2,imm2,#(1<<TCR_FLAG_BIT_ALLOCPTR_FOREIGN))
2864        __(str imm2,[rcontext,#tcr.flags])
2865        __(vpush1(rcontext))
2866        /* Hopefully safe now to use r3 (rcontext) and r12 (allocptr)
2867           as imm regs. */
2868pushdef(`q',`r0')
2869pushdef(`r',`r1')
2870pushdef(`s',`r2')
2871pushdef(`m',`r3')
2872pushdef(`a',`r12')
2873        __(clz s,q)
2874        __(movs a,q,lsl s)
2875        __(add a,pc,a,lsr #25)
2876        __(ldrbeq a,[a,#local_label(t32)-local_label(b32)-64])
2877local_label(b32):
2878        __(subs s,s,#7)
2879        __(rsb m,q,#0)
2880        __(movpl q,a,lsl s)
2881        __(mulpl a,q,m)
2882        __(bmi local_label(udiv_by_large_d))
2883        __(smlawt q,q,a,q)
2884        __(teq m,m,asr #1)
2885        __(mulne a,q,m)
2886        __(movne s,#0)
2887        __(smlalne s,q,a,q)
2888        __(beq local_label(udiv_by_1))
2889        __(umull s,q,r,q)
2890        __(add r,r,m)
2891        __(mla r,q,m,r)
2892        __(cmn r,m)
2893        __(subcs r,r,m)
2894        __(addcc q,q,#1)
2895        __(addpl r,r,m,lsl #1)
2896        __(addpl q,q,#2)
2897        __(b local_label(done))
2898local_label(udiv_by_large_d):       
2899        __(sub a,a,#4)
2900        __(rsb s,s,#0)
2901        __(mov q,a,lsr s)
2902        __(umull s,q,r,q)
2903        __(mla r,q,m,r)
2904        __(cmn m,r,lsr #1)
2905        __(addcs r,r,m,lsl #1)
2906        __(addcs q,q,#2)
2907        __(cmn m,r)
2908        __(addcs q,q,#1)
2909        __(b local_label(done))
2910local_label(udiv_by_1):
2911        __(mov q,r)
2912        __(mov r,#0)
2913local_label(done):   
2914        __(mov allocptr,#-8)
2915        __(vpop1(rcontext))
2916        __(ldr imm2,[rcontext,tcr.flags])
2917        __(bic imm2,imm2,#(1<<TCR_FLAG_BIT_ALLOCPTR_FOREIGN))
2918        __(str imm2,[rcontext,tcr.flags])
2919        __(ldr allocptr,[rcontext,tcr.save_allocptr])
2920        __(bx lr)
2921popdef(`s')
2922popdef(`m')
2923popdef(`a')
2924popdef(`q')
2925popdef(`r')
2926local_label(t32):   
2927        .byte 0xff,0xfc,0xf8,0xf4,0xf0,0xed,0xea,0xe6
2928        .byte 0xe3,0xe0,0xdd,0xda,0xd7,0xd4,0xd2,0xcf
2929        .byte 0xcc,0xca,0xc7,0xc5,0xc3,0xc0,0xbe,0xbc
2930        .byte 0xba,0xb8,0xb6,0xb4,0xb2,0xb0,0xae,0xac
2931        .byte 0xaa,0xa8,0xa7,0xa5,0xa3,0xa2,0xa0,0x9f
2932        .byte 0x9d,0x9c,0x9a,0x99,0x97,0x96,0x94,0x93
2933        .byte 0x92,0x90,0x8f,0x8e,0x8d,0x8c,0x8a,0x89
2934        .byte 0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81
2935
2936_spentry(sdiv32)
2937        __(build_lisp_frame(imm2))
2938pushdef(`sign',`temp0')
2939pushdef(`d',`r0')
2940pushdef(`r',`r1')               
2941        __(ands sign,d,#0x80000000)
2942        __(rsbmi d,d,#0)
2943        __(eors sign,sign,r,asr #32)
2944        __(rsbcs r,r,#0)
2945        __(bl _SPudiv32)
2946        __(movs sign,sign,lsl #1)
2947        __(rsbcs d,d,#0)
2948        __(rsbmi r,r,#0)
2949        __(return_lisp_frame(imm2))
2950popdef(`sign')
2951popdef(`d',)
2952popdef(`r',)               
2953       
2954
2955               
2956_spentry(eabi_ff_call)
2957        __(ldr arg_y,[rcontext,#tcr.last_lisp_frame])
2958        __(stmdb vsp!,{arg_y,arg_x,temp0,temp1,temp2})
2959/* There's a u32 vector on top of the stack ; its first data word points
2960   to the previous stack object.  The 4 words at the bottom of the vector
2961   are reserved for a lisp frame, which we construct carefully ... */
2962        __(mov imm0,#lisp_frame_marker)
2963        __(mov imm1,#0)
2964        __(ldr temp0,[sp,#4])
2965        __(sub temp0,temp0,#lisp_frame.size)
2966        __(str imm0,[temp0,#lisp_frame.marker])
2967        __(ldr imm0,[sp,#0])       
2968        __(str imm1,[temp0,#lisp_frame.savefn])
2969        __(str imm1,[temp0,#lisp_frame.savelr])
2970        __(sub imm0,imm0,#(lisp_frame.size/4)<<num_subtag_bits)
2971        __(str vsp,[temp0,#lisp_frame.savevsp])
2972        __(str imm0,[sp,#0])
2973        __(str lr,[temp0,#lisp_frame.savelr])
2974        __(str fn,[temp0,#lisp_frame.savefn])
2975        __(str allocptr,[rcontext,#tcr.save_allocptr])
2976        __(str temp0,[rcontext,#tcr.last_lisp_frame])
2977        __(mov temp0,rcontext)
2978        __(test_fixnum(arg_z))
2979        __(moveq imm1,arg_z,asr #fixnumshift)
2980        __(ldrne imm1,[arg_z,#misc_data_offset])
2981        __(mov imm0,#TCR_STATE_FOREIGN)
2982        __(str imm0,[rcontext,#tcr.valence])
2983        __(mov r4,imm1)
2984        __(add sp,sp,#dnode_size)
2985        __(ldmia sp!,{r0,r1,r2,r3})
2986        __(blx r4)
2987        __(mov temp1,#0)
2988        __(mov temp2,#0)
2989        __(mov arg_z,#0)
2990        __(mov arg_y,#0)
2991        __(mov arg_x,#0)
2992        __(mov fn,#0)
2993        __(mov allocptr,#VOID_ALLOCPTR)
2994        __(mov rcontext,temp0)
2995        __(ldr sp,[rcontext,#tcr.last_lisp_frame])
2996        __(str fn,[rcontext,#tcr.valence])
2997        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
2998        __(restore_lisp_frame(temp0))
2999        __(ldmia vsp!,{arg_y,arg_x,temp0,temp1,temp2})
3000        __(str arg_y,[rcontext,#tcr.last_lisp_frame])
3001        __(bx lr)
3002       
3003       
3004
3005_spentry(debind)
3006        new_local_labels()
3007        __(mov temp0,vsp)
3008        __(mov temp1,arg_z)
3009        __(ands imm0,nargs,#0xff)
3010        __(mov arg_y,#nil_value)
3011        __(b local_label(req_test))
3012local_label(req_loop): 
3013        __(cmp arg_reg,#nil_value)
3014        __(extract_lisptag(imm1,arg_reg))
3015        __(beq local_label(toofew))
3016        __(cmp imm1,#tag_list)
3017        __(bne local_label(badlist))
3018        __(subs imm0,imm0,#1)
3019        __(_car(arg_x,arg_reg))
3020        __(_cdr(arg_reg,arg_reg))
3021        __(vpush1(arg_x))
3022local_label(req_test):
3023        __(bne local_label(req_loop))
3024        __(mov imm0,#0xff)
3025        __(ands imm0,imm0,nargs,lsr #8)
3026        __(beq local_label(rest_keys))
3027        __(tst nargs,#mask_initopt)
3028        __(bne local_label(opt_supp))
3029        /* 'simple' &optionals:  no supplied-p, default to nil.   */
3030local_label(simple_opt_loop):
3031        __(cmp arg_reg,#nil_value)
3032        __(extract_lisptag(imm1,arg_reg))
3033        __(beq local_label(default_simple_opt))
3034        __(cmp imm1,#tag_list)
3035        __(bne local_label(badlist))
3036        __(subs imm0,imm0,#1)
3037        __(_car(arg_x,arg_reg))
3038        __(_cdr(arg_reg,arg_reg))
3039        __(vpush1(arg_x))
3040        __(bne local_label(simple_opt_loop))
3041        __(b local_label(rest_keys))
3042local_label(default_simple_opt):       
3043        __(subs imm0,imm0,#1)
3044        __(vpush1(arg_y))
3045        __(bne local_label(default_simple_opt))
3046        __(b local_label(rest_keys))
3047local_label(opt_supp):   
3048        __(cmp arg_reg,#nil_value)
3049        __(extract_lisptag(imm1,arg_reg))
3050        __(beq local_label(default_hard_opt))
3051        __(cmp imm1,#tag_list)
3052        __(bne local_label(badlist))
3053        __(subs imm0,imm0,#1)
3054        __(_car(arg_x,arg_reg))
3055        __(_cdr(arg_reg,arg_reg))
3056        __(vpush1(arg_x))
3057        __(add arg_x,arg_y,#t_offset)
3058        __(vpush1(arg_x))
3059        __(bne local_label(opt_supp))
3060        __(b local_label(rest_keys))
3061local_label(default_hard_opt): 
3062        __(subs imm0,imm0,#1)
3063        __(vpush1(arg_y))
3064        __(vpush1(arg_y))
3065        __(bne local_label(default_hard_opt))
3066local_label(rest_keys):
3067        __(tst nargs,#mask_restp)
3068        __(bne local_label(have_rest))
3069        __(tst nargs,#mask_keyp)
3070        __(bne local_label(have_keys))
3071        __(cmp arg_reg,#nil_value)
3072        __(bne local_label(toomany))
3073        __(bx lr)
3074local_label(have_rest):
3075        __(vpush1(arg_reg))
3076        __(tst nargs,#mask_keyp)
3077        __(bne local_label(have_keys))
3078        __(bx lr)
3079local_label(have_keys):
3080        __(mov imm0,#256)
3081        __(mov arg_y,arg_reg)
3082local_label(count_keys_loop):   
3083        __(cmp arg_y,#nil_value)
3084        __(beq local_label(counted_keys))
3085        __(subs imm0,imm0,#1)
3086        __(bmi local_label(toomany))
3087        __(extract_lisptag(imm1,arg_y))
3088        __(cmp imm1,#tag_list)
3089        __(bne local_label(badlist))
3090        __(_cdr(arg_y,arg_y))
3091        __(extract_lisptag(imm1,arg_y))
3092        __(cmp imm1,#tag_list)
3093        __(bne local_label(badlist))
3094        __(_cdr(arg_y,arg_y))
3095        __(b local_label(count_keys_loop))
3096local_label(counted_keys):     
3097        /* We've got a proper, even-length list of key/value pairs in  */
3098        /* arg_reg. For each keyword var in the lambda-list, push a pair  */
3099        /* of NILs on the vstack.  (We've also cdred down arg_y until it */
3100        /* contains NIL.) */
3101        __(mov imm0,#0xff)
3102        __(ands imm0,imm0,nargs,lsr #16)
3103        __(mov imm1,vsp)
3104        __(b local_label(push_pair_test))
3105local_label(push_pair_loop):
3106        __(subs imm0,imm0,#1)
3107        __(vpush1(arg_y))
3108        __(vpush1(arg_y))
3109local_label(push_pair_test):   
3110        __(bne local_label(push_pair_loop))
3111        __(b local_label(provided_key_loop))
3112       
3113local_label(next_provided_key):
3114        __(_car(arg_x,arg_reg))
3115        __(ref_nrs_symbol(imm0,kallowotherkeys,imm0))
3116        __(cmp arg_x,imm0)
3117        __(bne local_label(not_aok))
3118        __(tst nargs,#mask_aok_seen)
3119        __(beq local_label(not_aok))
3120        __(_cdr(arg_x,arg_reg))
3121        __(_car(arg_x,arg_x))
3122        __(orr nargs,nargs,#mask_aok_seen)
3123        __(cmp arg_x,#nil_value)
3124        __(orrne nargs,nargs,#mask_aok)
3125        __(_car(arg_x,arg_reg))
3126local_label(not_aok):   
3127        __(getvheader(imm0,keyvect_reg))
3128        __(header_length(arg_y,imm0))
3129        __(add imm0,arg_y,#misc_data_offset)
3130        __(b local_label(match_key_test))
3131local_label(match_key_loop):   
3132        __(ldr arg_y,[keyvect_reg,imm0])
3133        __(cmp arg_x,arg_y)
3134        __(bne local_label(match_key_test))
3135        __(sub imm0,imm0,#misc_data_offset)
3136        __(sub imm0,imm1,imm0,lsl #1)
3137        __(ldr arg_y,[imm0,#-node_size])
3138        __(cmp arg_y,#nil_value)
3139        __(beq local_label(provided_key_done))
3140        __(_cdr(arg_x,arg_reg))
3141        __(_car(arg_x,arg_x))
3142        __(str arg_x,[imm0,#0])
3143        __(mov arg_x,#nil_value)
3144        __(add arg_x,arg_x,#t_offset)
3145        __(str arg_x,[imm0,#-node_size])
3146        __(b local_label(provided_key_done))
3147local_label(match_key_test):   
3148        __(sub imm0,imm0,#node_size)
3149        __(cmp imm0,#misc_data_offset)
3150        __(bge local_label(match_key_loop))
3151        __(orr nargs,nargs,#mask_unknown_keyword_seen)
3152local_label(provided_key_done):
3153        __(_cdr(arg_reg,arg_reg))
3154        __(_cdr(arg_reg,arg_reg))
3155local_label(provided_key_loop):
3156        __(cmp arg_reg,#nil_value)
3157        __(bne local_label(next_provided_key))
3158        __(tst nargs,#mask_unknown_keyword_seen)
3159        __(bxeq lr)
3160        __(tst nargs,#mask_aok)
3161        __(bxne lr)
3162local_label(badkeys):
3163        __(mov arg_y,#XBADKEYS)
3164        __(b local_label(destructure_error))
3165local_label(toomany):   
3166        __(mov arg_y,#XCALLTOOMANY)
3167        __(b local_label(destructure_error))
3168local_label(toofew):   
3169        __(mov arg_y,#XCALLTOOFEW)
3170        __(b local_label(destructure_error))
3171local_label(badlist):   
3172        __(mov arg_y,#XCALLNOMATCH)
3173local_label(destructure_error):
3174        __(mov vsp,temp0)
3175        __(mov arg_z,temp1)       
3176        __(set_nargs(2))
3177        __(b _SPksignalerr)
3178       
3179
3180/*  EOF, basically  */
3181       
3182_exportfn(C(misc_ref_common))
3183        __(adr imm0,(local_label(misc_ref_jmp)))
3184        __(ldr pc,[imm0,imm1,lsl #2])       
3185
3186local_label(misc_ref_jmp):         
3187        /* 00-0f  */
3188        .long local_label(misc_ref_invalid) /* 00 even_fixnum  */
3189       
3190        .long local_label(misc_ref_invalid) /* 01 cons  */
3191        .long local_label(misc_ref_invalid) /* 02 nodeheader  */
3192        .long local_label(misc_ref_invalid) /* 03 imm  */
3193        .long local_label(misc_ref_invalid) /* 04 odd_fixnum  */
3194        .long local_label(misc_ref_invalid) /* 05 nil  */
3195        .long local_label(misc_ref_invalid) /* 06 misc  */
3196        .long local_label(misc_ref_u32) /* 07 bignum  */
3197        .long local_label(misc_ref_invalid) /* 08 even_fixnum  */
3198        .long local_label(misc_ref_invalid) /* 09 cons  */
3199        .long local_label(misc_ref_node) /* 0a ratio  */
3200        .long local_label(misc_ref_invalid) /* 0b imm  */
3201        .long local_label(misc_ref_invalid) /* 0c odd_fixnum  */
3202        .long local_label(misc_ref_invalid) /* 0d nil  */
3203        .long local_label(misc_ref_invalid) /* 0e misc  */
3204        .long local_label(misc_ref_u32) /* 0f single_float  */
3205        /* 10-1f  */
3206        .long local_label(misc_ref_invalid) /* 10 even_fixnum  */
3207        .long local_label(misc_ref_invalid) /* 11 cons  */
3208        .long local_label(misc_ref_invalid) /* 12 nodeheader  */
3209        .long local_label(misc_ref_invalid) /* 13 imm  */
3210        .long local_label(misc_ref_invalid) /* 14 odd_fixnum  */
3211        .long local_label(misc_ref_invalid) /* 15 nil  */
3212        .long local_label(misc_ref_invalid) /* 16 misc  */
3213        .long local_label(misc_ref_u32) /* 17 double_float  */
3214        .long local_label(misc_ref_invalid) /* 18 even_fixnum  */
3215        .long local_label(misc_ref_invalid) /* 19 cons  */
3216        .long local_label(misc_ref_node) /* 1a complex  */
3217        .long local_label(misc_ref_invalid) /* 1b imm  */
3218        .long local_label(misc_ref_invalid) /* 1c odd_fixnum  */
3219        .long local_label(misc_ref_invalid) /* 1d nil  */
3220        .long local_label(misc_ref_invalid) /* 1e misc  */
3221        .long local_label(misc_ref_u32) /* 1f macptr  */
3222        /* 20-2f  */
3223        .long local_label(misc_ref_invalid) /* 20 even_fixnum  */
3224        .long local_label(misc_ref_invalid) /* 21 cons  */
3225        .long local_label(misc_ref_node) /* 22 catch_frame  */
3226        .long local_label(misc_ref_invalid) /* 23 imm  */
3227        .long local_label(misc_ref_invalid) /* 24 odd_fixnum  */
3228        .long local_label(misc_ref_invalid) /* 25 nil  */
3229        .long local_label(misc_ref_invalid) /* 26 misc  */
3230        .long local_label(misc_ref_u32) /* 27 dead_macptr  */
3231        .long local_label(misc_ref_invalid) /* 28 even_fixnum  */
3232        .long local_label(misc_ref_invalid) /* 29 cons  */
3233        .long local_label(misc_ref_node) /* 2a function  */
3234        .long local_label(misc_ref_invalid) /* 2b imm  */
3235        .long local_label(misc_ref_invalid) /* 2c odd_fixnum  */
3236        .long local_label(misc_ref_invalid) /* 2d nil  */
3237        .long local_label(misc_ref_invalid) /* 2e misc  */
3238        .long local_label(misc_ref_u32) /* 2f code_vector  */
3239        /* 30-3f  */
3240        .long local_label(misc_ref_invalid) /* 30 even_fixnum  */
3241        .long local_label(misc_ref_invalid) /* 31 cons  */
3242        .long local_label(misc_ref_node) /* 32 lisp_thread  */
3243        .long local_label(misc_ref_invalid) /* 33 imm  */
3244        .long local_label(misc_ref_invalid) /* 34 odd_fixnum  */
3245        .long local_label(misc_ref_invalid) /* 35 nil  */
3246        .long local_label(misc_ref_invalid) /* 36 misc  */
3247        .long local_label(misc_ref_u32) /* 37 creole  */
3248        .long local_label(misc_ref_invalid) /* 38 even_fixnum  */
3249        .long local_label(misc_ref_invalid) /* 39 cons  */
3250        .long local_label(misc_ref_node) /* 3a symbol  */
3251        .long local_label(misc_ref_invalid) /* 3b imm  */
3252        .long local_label(misc_ref_invalid) /* 3c odd_fixnum  */
3253        .long local_label(misc_ref_invalid) /* 3d nil  */
3254        .long local_label(misc_ref_invalid) /* 3e misc  */
3255        .long local_label(misc_ref_u32) /* 3f xcode_vector  */
3256        /* 40-4f  */
3257        .long local_label(misc_ref_invalid) /* 40 even_fixnum  */
3258        .long local_label(misc_ref_invalid) /* 41 cons  */
3259        .long local_label(misc_ref_node) /* 42 lock  */
3260        .long local_label(misc_ref_invalid) /* 43 imm  */
3261        .long local_label(misc_ref_invalid) /* 44 odd_fixnum  */
3262        .long local_label(misc_ref_invalid) /* 45 nil  */
3263        .long local_label(misc_ref_invalid) /* 46 misc  */
3264        .long local_label(misc_ref_invalid) /* 47 immheader  */
3265        .long local_label(misc_ref_invalid) /* 48 even_fixnum  */
3266        .long local_label(misc_ref_invalid) /* 49 cons  */
3267        .long local_label(misc_ref_node) /* 4a hash_vector  */
3268        .long local_label(misc_ref_invalid) /* 4b imm  */
3269        .long local_label(misc_ref_invalid) /* 4c odd_fixnum  */
3270        .long local_label(misc_ref_invalid) /* 4d nil  */
3271        .long local_label(misc_ref_invalid) /* 4e misc  */
3272        .long local_label(misc_ref_invalid) /* 4f immheader  */
3273        /* 50-5f  */
3274        .long local_label(misc_ref_invalid) /* 50 even_fixnum  */
3275        .long local_label(misc_ref_invalid) /* 51 cons  */
3276        .long local_label(misc_ref_node) /* 52 pool  */
3277        .long local_label(misc_ref_invalid) /* 53 imm  */
3278        .long local_label(misc_ref_invalid) /* 54 odd_fixnum  */
3279        .long local_label(misc_ref_invalid) /* 55 nil  */
3280        .long local_label(misc_ref_invalid) /* 56 misc  */
3281        .long local_label(misc_ref_invalid) /* 57 immheader  */
3282        .long local_label(misc_ref_invalid) /* 58 even_fixnum  */
3283        .long local_label(misc_ref_invalid) /* 59 cons  */
3284        .long local_label(misc_ref_node) /* 5a weak  */
3285        .long local_label(misc_ref_invalid) /* 5b imm  */
3286        .long local_label(misc_ref_invalid) /* 5c odd_fixnum  */
3287        .long local_label(misc_ref_invalid) /* 5d nil  */
3288        .long local_label(misc_ref_invalid) /* 5e misc  */
3289        .long local_label(misc_ref_invalid) /* 5f immheader  */
3290        /* 60-6f  */
3291        .long local_label(misc_ref_invalid) /* 60 even_fixnum  */
3292        .long local_label(misc_ref_invalid) /* 61 cons  */
3293        .long local_label(misc_ref_node) /* 62 package  */
3294        .long local_label(misc_ref_invalid) /* 63 imm  */
3295        .long local_label(misc_ref_invalid) /* 64 odd_fixnum  */
3296        .long local_label(misc_ref_invalid) /* 65 nil  */
3297        .long local_label(misc_ref_invalid) /* 66 misc  */
3298        .long local_label(misc_ref_invalid) /* 67 immheader  */
3299        .long local_label(misc_ref_invalid) /* 68 even_fixnum  */
3300        .long local_label(misc_ref_invalid) /* 69 cons  */
3301        .long local_label(misc_ref_node) /* 6a slot_vector  */
3302        .long local_label(misc_ref_invalid) /* 6b imm  */
3303        .long local_label(misc_ref_invalid) /* 6c odd_fixnum  */
3304        .long local_label(misc_ref_invalid) /* 6d nil  */
3305        .long local_label(misc_ref_invalid) /* 6e misc  */
3306        .long local_label(misc_ref_invalid) /* 6f immheader  */
3307        /* 70-7f  */
3308        .long local_label(misc_ref_invalid) /* 70 even_fixnum  */
3309        .long local_label(misc_ref_invalid) /* 71 cons  */
3310        .long local_label(misc_ref_node) /* 72 instance  */
3311        .long local_label(misc_ref_invalid) /* 73 imm  */
3312        .long local_label(misc_ref_invalid) /* 74 odd_fixnum  */
3313        .long local_label(misc_ref_invalid) /* 75 nil  */
3314        .long local_label(misc_ref_invalid) /* 76 misc  */
3315        .long local_label(misc_ref_invalid) /* 77 immheader  */
3316        .long local_label(misc_ref_invalid) /* 78 even_fixnum  */
3317        .long local_label(misc_ref_invalid) /* 79 cons  */
3318        .long local_label(misc_ref_node) /* 7a struct  */
3319        .long local_label(misc_ref_invalid) /* 7b imm  */
3320        .long local_label(misc_ref_invalid) /* 7c odd_fixnum  */
3321        .long local_label(misc_ref_invalid) /* 7d nil  */
3322        .long local_label(misc_ref_invalid) /* 7e misc  */
3323        .long local_label(misc_ref_invalid) /* 7f immheader  */
3324        /* 80-8f  */
3325        .long local_label(misc_ref_invalid) /* 80 even_fixnum  */
3326        .long local_label(misc_ref_invalid) /* 81 cons  */
3327        .long local_label(misc_ref_node) /* 82 istruct  */
3328        .long local_label(misc_ref_invalid) /* 83 imm  */
3329        .long local_label(misc_ref_invalid) /* 84 odd_fixnum  */
3330        .long local_label(misc_ref_invalid) /* 85 nil  */
3331        .long local_label(misc_ref_invalid) /* 86 misc  */
3332        .long local_label(misc_ref_invalid) /* 87 immheader  */
3333        .long local_label(misc_ref_invalid) /* 88 even_fixnum  */
3334        .long local_label(misc_ref_invalid) /* 89 cons  */
3335        .long local_label(misc_ref_node) /* 8a value_cell  */
3336        .long local_label(misc_ref_invalid) /* 8b imm  */
3337        .long local_label(misc_ref_invalid) /* 8c odd_fixnum  */
3338        .long local_label(misc_ref_invalid) /* 8d nil  */
3339        .long local_label(misc_ref_invalid) /* 8e misc  */
3340        .long local_label(misc_ref_invalid) /* 8f immheader  */
3341        /* 90-9f  */
3342        .long local_label(misc_ref_invalid) /* 90 even_fixnum  */
3343        .long local_label(misc_ref_invalid) /* 91 cons  */
3344        .long local_label(misc_ref_node) /* 92 xfunction  */
3345        .long local_label(misc_ref_invalid) /* 93 imm  */
3346        .long local_label(misc_ref_invalid) /* 94 odd_fixnum  */
3347        .long local_label(misc_ref_invalid) /* 95 nil  */
3348        .long local_label(misc_ref_invalid) /* 96 misc  */
3349        .long local_label(misc_ref_invalid) /* 97 immheader  */
3350        .long local_label(misc_ref_invalid) /* 98 even_fixnum  */
3351        .long local_label(misc_ref_invalid) /* 99 cons  */
3352        .long local_label(misc_ref_node) /* 9a arrayN  */
3353        .long local_label(misc_ref_invalid) /* 9b imm  */
3354        .long local_label(misc_ref_invalid) /* 9c odd_fixnum  */
3355        .long local_label(misc_ref_invalid) /* 9d nil  */
3356        .long local_label(misc_ref_invalid) /* 9e misc  */
3357        .long local_label(misc_ref_invalid) /* 9f immheader  */
3358        /* a0-af  */
3359        .long local_label(misc_ref_invalid) /* a0 even_fixnum  */
3360        .long local_label(misc_ref_invalid) /* a1 cons  */
3361        .long local_label(misc_ref_node) /* a2 vectorH  */
3362        .long local_label(misc_ref_invalid) /* a3 imm  */
3363        .long local_label(misc_ref_invalid) /* a4 odd_fixnum  */
3364        .long local_label(misc_ref_invalid) /* a5 nil  */
3365        .long local_label(misc_ref_invalid) /* a6 misc  */
3366        .long local_label(misc_ref_single_float_vector) /* a7 sf_vector  */
3367        .long local_label(misc_ref_invalid) /* a8 even_fixnum  */
3368        .long local_label(misc_ref_invalid) /* a9 cons  */
3369        .long local_label(misc_ref_node) /* aa simple_vector  */
3370        .long local_label(misc_ref_invalid) /* ab imm  */
3371        .long local_label(misc_ref_invalid) /* ac odd_fixnum  */
3372        .long local_label(misc_ref_invalid) /* ad nil  */
3373        .long local_label(misc_ref_invalid) /* ae misc  */
3374        .long local_label(misc_ref_u32) /* af u32  */
3375        /* b0-bf  */
3376        .long local_label(misc_ref_invalid) /* b0 even_fixnum  */
3377        .long local_label(misc_ref_invalid) /* b1 cons  */
3378        .long local_label(misc_ref_invalid) /* b2 nodeheader  */
3379        .long local_label(misc_ref_invalid) /* b3 imm  */
3380        .long local_label(misc_ref_invalid) /* b4 odd_fixnum  */
3381        .long local_label(misc_ref_invalid) /* b5 nil  */
3382        .long local_label(misc_ref_invalid) /* b6 misc  */
3383        .long local_label(misc_ref_s32) /* b7 s32  */
3384        .long local_label(misc_ref_invalid) /* b8 even_fixnum  */
3385        .long local_label(misc_ref_invalid) /* b9 cons  */
3386        .long local_label(misc_ref_invalid) /* ba nodeheader  */
3387        .long local_label(misc_ref_invalid) /* bb imm  */
3388        .long local_label(misc_ref_invalid) /* bc odd_fixnum  */
3389        .long local_label(misc_ref_invalid) /* bd nil  */
3390        .long local_label(misc_ref_invalid) /* be misc  */
3391        .long local_label(misc_ref_fixnum_vector) /* bf fixnum_vector  */
3392        /* c0-cf  */
3393        .long local_label(misc_ref_invalid) /* c0 even_fixnum  */
3394        .long local_label(misc_ref_invalid) /* c1 cons  */
3395        .long local_label(misc_ref_invalid) /* c2 nodeheader  */
3396        .long local_label(misc_ref_invalid) /* c3 imm  */
3397        .long local_label(misc_ref_invalid) /* c4 odd_fixnum  */
3398        .long local_label(misc_ref_invalid) /* c5 nil  */
3399        .long local_label(misc_ref_invalid) /* c6 misc  */
3400        .long local_label(misc_ref_new_string) /* c7 new_string  */
3401        .long local_label(misc_ref_invalid) /* c8 even_fixnum  */
3402        .long local_label(misc_ref_invalid) /* c9 cons  */
3403        .long local_label(misc_ref_invalid) /* ca nodeheader  */
3404        .long local_label(misc_ref_invalid) /* cb imm  */
3405        .long local_label(misc_ref_invalid) /* cc odd_fixnum  */
3406        .long local_label(misc_ref_invalid) /* cd nil  */
3407        .long local_label(misc_ref_invalid) /* ce misc  */
3408        .long local_label(misc_ref_u8) /* cf u8  */
3409        /* d0-df  */
3410        .long local_label(misc_ref_invalid) /* d0 even_fixnum  */
3411        .long local_label(misc_ref_invalid) /* d1 cons  */
3412        .long local_label(misc_ref_invalid) /* d2 nodeheader  */
3413        .long local_label(misc_ref_invalid) /* d3 imm  */
3414        .long local_label(misc_ref_invalid) /* d4 odd_fixnum  */
3415        .long local_label(misc_ref_invalid) /* d5 nil  */
3416        .long local_label(misc_ref_invalid) /* d6 misc  */
3417        .long local_label(misc_ref_s8)      /* d7 s8  */
3418        .long local_label(misc_ref_invalid) /* d8 even_fixnum  */
3419        .long local_label(misc_ref_invalid) /* d9 cons  */
3420        .long local_label(misc_ref_invalid) /* da nodeheader  */
3421        .long local_label(misc_ref_invalid) /* db imm  */
3422        .long local_label(misc_ref_invalid) /* dc odd_fixnum  */
3423        .long local_label(misc_ref_invalid) /* dd nil  */
3424        .long local_label(misc_ref_invalid) /* de misc  */
3425        .long local_label(misc_ref_old_string) /* df (old)subtag_simple_base_string  */
3426        /* e0-ef  */
3427        .long local_label(misc_ref_invalid) /* e0 even_fixnum  */
3428        .long local_label(misc_ref_invalid) /* e1 cons  */
3429        .long local_label(misc_ref_invalid) /* e2 nodeheader  */
3430        .long local_label(misc_ref_invalid) /* e3 imm  */
3431        .long local_label(misc_ref_invalid) /* e4 odd_fixnum  */
3432        .long local_label(misc_ref_invalid) /* e5 nil  */
3433        .long local_label(misc_ref_invalid) /* e6 misc  */
3434        .long local_label(misc_ref_u16) /* e7 u16  */
3435        .long local_label(misc_ref_invalid) /* e8 even_fixnum  */
3436        .long local_label(misc_ref_invalid) /* e9 cons  */
3437        .long local_label(misc_ref_invalid) /* ea nodeheader  */
3438        .long local_label(misc_ref_invalid) /* eb imm  */
3439        .long local_label(misc_ref_invalid) /* ec odd_fixnum  */
3440        .long local_label(misc_ref_invalid) /* ed nil  */
3441        .long local_label(misc_ref_invalid) /* ee misc  */
3442        .long local_label(misc_ref_s16) /* ef s16  */
3443        /* f0-ff  */
3444        .long local_label(misc_ref_invalid) /* f0 even_fixnum  */
3445        .long local_label(misc_ref_invalid) /* f1 cons  */
3446        .long local_label(misc_ref_invalid) /* f2 nodeheader  */
3447        .long local_label(misc_ref_invalid) /* f3 imm  */
3448        .long local_label(misc_ref_invalid) /* f4 odd_fixnum  */
3449        .long local_label(misc_ref_invalid) /* f5 nil  */
3450        .long local_label(misc_ref_invalid) /* f6 misc  */
3451        .long local_label(misc_ref_double_float_vector) /* f7 df vector  */
3452        .long local_label(misc_ref_invalid) /* f8 even_fixnum  */
3453        .long local_label(misc_ref_invalid) /* f9 cons  */
3454        .long local_label(misc_ref_invalid) /* fa nodeheader  */
3455        .long local_label(misc_ref_invalid) /* fb imm  */
3456        .long local_label(misc_ref_invalid) /* fc odd_fixnum  */
3457        .long local_label(misc_ref_invalid) /* fd nil  */
3458        .long local_label(misc_ref_invalid) /* fe misc  */
3459        .long local_label(misc_ref_bit_vector) /* ff bit_vector  */
3460
3461local_label(misc_ref_node):       
3462        /* A node vector.  */
3463        __(add imm0,arg_z,#misc_data_offset)
3464        __(ldr  arg_z,[arg_y,imm0])
3465        __(bx lr)
3466local_label(misc_ref_single_float_vector):       
3467        __(add imm0,arg_z,misc_data_offset)
3468        __(movc16(imm1,single_float_header))
3469        __(ldr imm0,[arg_y,imm0])
3470        __(Misc_Alloc_Fixed(arg_z,imm1,single_float.size))
3471        __(str imm0,[arg_z,#single_float.value])
3472        __(bx lr)
3473local_label(misc_ref_new_string):       
3474        __(add imm0,arg_z,#misc_data_offset)
3475        __(ldr imm0,[arg_y,imm0])
3476        __(mov arg_z,imm0,lsl #charcode_shift)
3477        __(orr arg_z,arg_z,#subtag_character)
3478        __(bx lr)
3479local_label(misc_ref_s32):       
3480        __(add imm0,arg_z,#misc_data_offset)
3481        __(ldr imm0,[arg_y,imm0])
3482        __(b _SPmakes32)
3483local_label(misc_ref_fixnum_vector):   
3484        __(add imm0,arg_z,#misc_data_offset)
3485        __(ldr imm0,[arg_y,imm0])
3486        __(box_fixnum(arg_z,imm0))
3487        __(bx lr)       
3488local_label(misc_ref_u32):       
3489        __(add imm0,arg_z,#misc_data_offset)
3490        __(ldr imm0,[arg_y,imm0])
3491        __(b _SPmakeu32)
3492local_label(misc_ref_double_float_vector):     
3493        __(mov imm0,arg_z,lsl #1)
3494        __(add imm0,imm0,#misc_dfloat_offset)
3495        __(ldrd imm0,imm1,[arg_y,imm0])
3496        __(movc16(imm2,double_float_header))
3497        __(Misc_Alloc_Fixed(arg_z,imm2,double_float.size))
3498        __(strd imm0,imm1,[arg_z,#double_float.value])
3499        __(bx lr)
3500local_label(misc_ref_bit_vector):
3501        __(mov imm1,#nbits_in_word-1)
3502        __(and imm1,imm1,arg_z,lsr #2)
3503        __(mov imm2,#1)
3504        __(mov imm2,imm2,lsl imm1)
3505        __(mov imm0,arg_z,lsr #5+fixnumshift)
3506        __(mov imm0,imm0,lsl #2)
3507        __(add imm0,imm0,#misc_data_offset)
3508        __(mov arg_z,#0)
3509        __(ldr imm0,[arg_y,imm0])
3510        __(tst imm0,imm2)
3511        __(addne arg_z,arg_z,#fixnumone)
3512        __(bx lr)
3513local_label(misc_ref_s8):       
3514        __(mov imm0,arg_z,lsr #2)
3515        __(add imm0,imm0,#misc_data_offset)
3516        __(ldsb imm0,[arg_y,imm0])
3517        __(box_fixnum(arg_z,imm0))
3518        __(bx lr)
3519local_label(misc_ref_u8):       
3520        __(mov imm0,arg_z,lsr #2)
3521        __(add imm0,imm0,#misc_data_offset)
3522        __(ldrb imm0,[arg_y,imm0])
3523        __(box_fixnum(arg_z,imm0))
3524        __(bx lr)
3525local_label(misc_ref_old_string):         
3526        __(mov imm0,arg_z,lsr #2)
3527        __(add imm0,imm0,#misc_data_offset)
3528        __(ldrb imm0,[arg_y,imm0])
3529        __(mov arg_z,imm0,lsl #charcode_shift)
3530        __(orr arg_z,arg_z,#subtag_character)
3531        __(bx lr)
3532local_label(misc_ref_u16):       
3533        __(mov imm0,arg_z,lsr #1)     
3534        __(add imm0,imm0,#misc_data_offset)
3535        __(ldrh imm0,[arg_y,imm0])
3536        __(box_fixnum(arg_z,imm0))
3537        __(bx lr)
3538local_label(misc_ref_s16):             
3539        __(mov imm0,arg_z,lsr #1)     
3540        __(add imm0,imm0,#misc_data_offset)
3541        __(ldrsh imm0,[arg_y,imm0])
3542        __(box_fixnum(arg_z,imm0))
3543        __(bx lr)
3544local_label(misc_ref_invalid):
3545        __(mov arg_x,#XBADVEC)
3546        __(set_nargs(3))
3547        __(b _SPksignalerr)       
3548_endfn
3549       
3550_exportfn(C(misc_set_common))
3551        __(adr imm0,local_label(misc_set_jmp))
3552        __(ldr pc,[imm0,imm1,lsl #2])
3553local_label(misc_set_jmp):             
3554        /* 00-0f  */
3555        .long local_label(misc_set_invalid) /* 00 even_fixnum  */
3556        .long local_label(misc_set_invalid) /* 01 cons  */
3557        .long local_label(misc_set_invalid) /* 02 nodeheader  */
3558        .long local_label(misc_set_invalid) /* 03 imm  */
3559        .long local_label(misc_set_invalid) /* 04 odd_fixnum  */
3560        .long local_label(misc_set_invalid) /* 05 nil  */
3561        .long local_label(misc_set_invalid) /* 06 misc  */
3562        .long local_label(misc_set_u32) /* 07 bignum  */
3563        .long local_label(misc_set_invalid) /* 08 even_fixnum  */
3564        .long local_label(misc_set_invalid) /* 09 cons  */
3565        .long _SPgvset /* 0a ratio  */
3566        .long local_label(misc_set_invalid) /* 0b imm  */
3567        .long local_label(misc_set_invalid) /* 0c odd_fixnum  */
3568        .long local_label(misc_set_invalid) /* 0d nil  */
3569        .long local_label(misc_set_invalid) /* 0e misc  */
3570        .long local_label(misc_set_u32) /* 0f single_float  */
3571        /* 10-1f  */
3572        .long local_label(misc_set_invalid) /* 10 even_fixnum  */
3573        .long local_label(misc_set_invalid) /* 11 cons  */
3574        .long local_label(misc_set_invalid) /* 12 nodeheader  */
3575        .long local_label(misc_set_invalid) /* 13 imm  */
3576        .long local_label(misc_set_invalid) /* 14 odd_fixnum  */
3577        .long local_label(misc_set_invalid) /* 15 nil  */
3578        .long local_label(misc_set_invalid) /* 16 misc  */
3579        .long local_label(misc_set_u32) /* 17 double_float  */
3580        .long local_label(misc_set_invalid) /* 18 even_fixnum  */
3581        .long local_label(misc_set_invalid) /* 19 cons  */
3582        .long _SPgvset /* 1a complex  */
3583        .long local_label(misc_set_invalid) /* 1b imm  */
3584        .long local_label(misc_set_invalid) /* 1c odd_fixnum  */
3585        .long local_label(misc_set_invalid) /* 1d nil  */
3586        .long local_label(misc_set_invalid) /* 1e misc  */
3587        .long local_label(misc_set_u32) /* 1f macptr  */
3588        /* 20-2f  */
3589        .long local_label(misc_set_invalid) /* 20 even_fixnum  */
3590        .long local_label(misc_set_invalid) /* 21 cons  */
3591        .long _SPgvset /* 22 catch_frame  */
3592        .long local_label(misc_set_invalid) /* 23 imm  */
3593        .long local_label(misc_set_invalid) /* 24 odd_fixnum  */
3594        .long local_label(misc_set_invalid) /* 25 nil  */
3595        .long local_label(misc_set_invalid) /* 26 misc  */
3596        .long local_label(misc_set_u32) /* 27 dead_macptr  */
3597        .long local_label(misc_set_invalid) /* 28 even_fixnum  */
3598        .long local_label(misc_set_invalid) /* 29 cons  */
3599        .long _SPgvset /* 2a function  */
3600        .long local_label(misc_set_invalid) /* 2b imm  */
3601        .long local_label(misc_set_invalid) /* 2c odd_fixnum  */
3602        .long local_label(misc_set_invalid) /* 2d nil  */
3603        .long local_label(misc_set_invalid) /* 2e misc  */
3604        .long local_label(misc_set_u32) /* 2f code_vector  */
3605        /* 30-3f  */
3606        .long local_label(misc_set_invalid) /* 30 even_fixnum  */
3607        .long local_label(misc_set_invalid) /* 31 cons  */
3608        .long _SPgvset /* 32 lisp_thread  */
3609        .long local_label(misc_set_invalid) /* 33 imm  */
3610        .long local_label(misc_set_invalid) /* 34 odd_fixnum  */
3611        .long local_label(misc_set_invalid) /* 35 nil  */
3612        .long local_label(misc_set_invalid) /* 36 misc  */
3613        .long local_label(misc_set_u32) /* 37 creole  */
3614        .long local_label(misc_set_invalid) /* 38 even_fixnum  */
3615        .long local_label(misc_set_invalid) /* 39 cons  */
3616        .long _SPgvset /* 3a symbol  */
3617        .long local_label(misc_set_invalid) /* 3b imm  */
3618        .long local_label(misc_set_invalid) /* 3c odd_fixnum  */
3619        .long local_label(misc_set_invalid) /* 3d nil  */
3620        .long local_label(misc_set_invalid) /* 3e misc  */
3621        .long local_label(misc_set_u32) /* 3f xcode_vector  */
3622        /* 40-4f  */
3623        .long local_label(misc_set_invalid) /* 40 even_fixnum  */
3624        .long local_label(misc_set_invalid) /* 41 cons  */
3625        .long _SPgvset /* 42 lock  */
3626        .long local_label(misc_set_invalid) /* 43 imm  */
3627        .long local_label(misc_set_invalid) /* 44 odd_fixnum  */
3628        .long local_label(misc_set_invalid) /* 45 nil  */
3629        .long local_label(misc_set_invalid) /* 46 misc  */
3630        .long local_label(misc_set_invalid) /* 47 immheader  */
3631        .long local_label(misc_set_invalid) /* 48 even_fixnum  */
3632        .long local_label(misc_set_invalid) /* 49 cons  */
3633        .long _SPgvset /* 4a hash_vector  */
3634        .long local_label(misc_set_invalid) /* 4b imm  */
3635        .long local_label(misc_set_invalid) /* 4c odd_fixnum  */
3636        .long local_label(misc_set_invalid) /* 4d nil  */
3637        .long local_label(misc_set_invalid) /* 4e misc  */
3638        .long local_label(misc_set_invalid) /* 4f immheader  */
3639        /* 50-5f  */
3640        .long local_label(misc_set_invalid) /* 50 even_fixnum  */
3641        .long local_label(misc_set_invalid) /* 51 cons  */
3642        .long _SPgvset /* 52 pool  */
3643        .long local_label(misc_set_invalid) /* 53 imm  */
3644        .long local_label(misc_set_invalid) /* 54 odd_fixnum  */
3645        .long local_label(misc_set_invalid) /* 55 nil  */
3646        .long local_label(misc_set_invalid) /* 56 misc  */
3647        .long local_label(misc_set_invalid) /* 57 immheader  */
3648        .long local_label(misc_set_invalid) /* 58 even_fixnum  */
3649        .long local_label(misc_set_invalid) /* 59 cons  */
3650        .long _SPgvset /* 5a weak  */
3651        .long local_label(misc_set_invalid) /* 5b imm  */
3652        .long local_label(misc_set_invalid) /* 5c odd_fixnum  */
3653        .long local_label(misc_set_invalid) /* 5d nil  */
3654        .long local_label(misc_set_invalid) /* 5e misc  */
3655        .long local_label(misc_set_invalid) /* 5f immheader  */
3656        /* 60-6f  */
3657        .long local_label(misc_set_invalid) /* 60 even_fixnum  */
3658        .long local_label(misc_set_invalid) /* 61 cons  */
3659        .long _SPgvset /* 62 package  */
3660        .long local_label(misc_set_invalid) /* 63 imm  */
3661        .long local_label(misc_set_invalid) /* 64 odd_fixnum  */
3662        .long local_label(misc_set_invalid) /* 65 nil  */
3663        .long local_label(misc_set_invalid) /* 66 misc  */
3664        .long local_label(misc_set_invalid) /* 67 immheader  */
3665        .long local_label(misc_set_invalid) /* 68 even_fixnum  */
3666        .long local_label(misc_set_invalid) /* 69 cons  */
3667        .long _SPgvset /* 6a slot_vector  */
3668        .long local_label(misc_set_invalid) /* 6b imm  */
3669        .long local_label(misc_set_invalid) /* 6c odd_fixnum  */
3670        .long local_label(misc_set_invalid) /* 6d nil  */
3671        .long local_label(misc_set_invalid) /* 6e misc  */
3672        .long local_label(misc_set_invalid) /* 6f immheader  */
3673        /* 70-7f  */
3674        .long local_label(misc_set_invalid) /* 70 even_fixnum  */
3675        .long local_label(misc_set_invalid) /* 71 cons  */
3676        .long _SPgvset /* 72 instance  */
3677        .long local_label(misc_set_invalid) /* 73 imm  */
3678        .long local_label(misc_set_invalid) /* 74 odd_fixnum  */
3679        .long local_label(misc_set_invalid) /* 75 nil  */
3680        .long local_label(misc_set_invalid) /* 76 misc  */
3681        .long local_label(misc_set_invalid) /* 77 immheader  */
3682        .long local_label(misc_set_invalid) /* 78 even_fixnum  */
3683        .long local_label(misc_set_invalid) /* 79 cons  */
3684        .long _SPgvset /* 7a struct  */
3685        .long local_label(misc_set_invalid) /* 7b imm  */
3686        .long local_label(misc_set_invalid) /* 7c odd_fixnum  */
3687        .long local_label(misc_set_invalid) /* 7d nil  */
3688        .long local_label(misc_set_invalid) /* 7e misc  */
3689        .long local_label(misc_set_invalid) /* 7f immheader  */
3690        /* 80-8f  */
3691        .long local_label(misc_set_invalid) /* 80 even_fixnum  */
3692        .long local_label(misc_set_invalid) /* 81 cons  */
3693        .long _SPgvset /* 82 istruct  */
3694        .long local_label(misc_set_invalid) /* 83 imm  */
3695        .long local_label(misc_set_invalid) /* 84 odd_fixnum  */
3696        .long local_label(misc_set_invalid) /* 85 nil  */
3697        .long local_label(misc_set_invalid) /* 86 misc  */
3698        .long local_label(misc_set_invalid) /* 87 immheader  */
3699        .long local_label(misc_set_invalid) /* 88 even_fixnum  */
3700        .long local_label(misc_set_invalid) /* 89 cons  */
3701        .long _SPgvset /* 8a value_cell  */
3702        .long local_label(misc_set_invalid) /* 8b imm  */
3703        .long local_label(misc_set_invalid) /* 8c odd_fixnum  */
3704        .long local_label(misc_set_invalid) /* 8d nil  */
3705        .long local_label(misc_set_invalid) /* 8e misc  */
3706        .long local_label(misc_set_invalid) /* 8f immheader  */
3707        /* 90-9f  */
3708        .long local_label(misc_set_invalid) /* 90 even_fixnum  */
3709        .long local_label(misc_set_invalid) /* 91 cons  */
3710        .long _SPgvset /* 92 xfunction  */
3711        .long local_label(misc_set_invalid) /* 93 imm  */
3712        .long local_label(misc_set_invalid) /* 94 odd_fixnum  */
3713        .long local_label(misc_set_invalid) /* 95 nil  */
3714        .long local_label(misc_set_invalid) /* 96 misc  */
3715        .long local_label(misc_set_invalid) /* 97 immheader  */
3716        .long local_label(misc_set_invalid) /* 98 even_fixnum  */
3717        .long local_label(misc_set_invalid) /* 99 cons  */
3718        .long _SPgvset /* 9a arrayH  */
3719        .long local_label(misc_set_invalid) /* 9b imm  */
3720        .long local_label(misc_set_invalid) /* 9c odd_fixnum  */
3721        .long local_label(misc_set_invalid) /* 9d nil  */
3722        .long local_label(misc_set_invalid) /* 9e misc  */
3723        .long local_label(misc_set_invalid) /* 9f immheader  */
3724        /* a0-af  */
3725        .long local_label(misc_set_invalid) /* a0 even_fixnum  */
3726        .long local_label(misc_set_invalid) /* a1 cons  */
3727        .long _SPgvset /* a2 vectorH  */
3728        .long local_label(misc_set_invalid) /* a3 imm  */
3729        .long local_label(misc_set_invalid) /* a4 odd_fixnum  */
3730        .long local_label(misc_set_invalid) /* a5 nil  */
3731        .long local_label(misc_set_invalid) /* a6 misc  */
3732        .long local_label(misc_set_single_float_vector) /* a7 sf vector  */
3733        .long local_label(misc_set_invalid) /* a8 even_fixnum  */
3734        .long local_label(misc_set_invalid) /* a9 cons  */
3735        .long _SPgvset /* aa vectorH  */
3736        .long local_label(misc_set_invalid) /* ab imm  */
3737        .long local_label(misc_set_invalid) /* ac odd_fixnum  */
3738        .long local_label(misc_set_invalid) /* ad nil  */
3739        .long local_label(misc_set_invalid) /* ae misc  */
3740        .long local_label(misc_set_u32) /* af u32  */
3741        /* b0-bf  */
3742        .long local_label(misc_set_invalid) /* b0 even_fixnum  */
3743        .long local_label(misc_set_invalid) /* b1 cons  */
3744        .long local_label(misc_set_invalid) /* b2 node  */
3745        .long local_label(misc_set_invalid) /* b3 imm  */
3746        .long local_label(misc_set_invalid) /* b4 odd_fixnum  */
3747        .long local_label(misc_set_invalid) /* b5 nil  */
3748        .long local_label(misc_set_invalid) /* b6 misc  */
3749        .long local_label(misc_set_s32) /* b7 s32  */
3750        .long local_label(misc_set_invalid) /* b8 even_fixnum  */
3751        .long local_label(misc_set_invalid) /* b9 cons  */
3752        .long local_label(misc_set_invalid) /* ba nodeheader  */
3753        .long local_label(misc_set_invalid) /* bb imm  */
3754        .long local_label(misc_set_invalid) /* bc odd_fixnum  */
3755        .long local_label(misc_set_invalid) /* bd nil  */
3756        .long local_label(misc_set_invalid) /* be misc  */
3757        .long local_label(misc_set_fixnum_vector) /* bf fixnum_vector  */
3758        /* c0-cf  */
3759        .long local_label(misc_set_invalid) /* c0 even_fixnum  */
3760        .long local_label(misc_set_invalid) /* c1 cons  */
3761        .long local_label(misc_set_invalid) /* c2 nodeheader  */
3762        .long local_label(misc_set_invalid) /* c3 imm  */
3763        .long local_label(misc_set_invalid) /* c4 odd_fixnum  */
3764        .long local_label(misc_set_invalid) /* c5 nil  */
3765        .long local_label(misc_set_invalid) /* c6 misc  */
3766        .long local_label(misc_set_new_string) /* c7 new_string  */
3767        .long local_label(misc_set_invalid) /* c8 even_fixnum  */
3768        .long local_label(misc_set_invalid) /* c9 cons  */
3769        .long local_label(misc_set_invalid) /* ca nodeheader  */
3770        .long local_label(misc_set_invalid) /* cb imm  */
3771        .long local_label(misc_set_invalid) /* cc odd_fixnum  */
3772        .long local_label(misc_set_invalid) /* cd nil  */
3773        .long local_label(misc_set_invalid) /* ce misc  */
3774        .long local_label(misc_set_u8) /* cf u8  */
3775        /* d0-df  */
3776        .long local_label(misc_set_invalid) /* d0 even_fixnum  */
3777        .long local_label(misc_set_invalid) /* d1 cons  */
3778        .long local_label(misc_set_invalid) /* d2 nodeheader  */
3779        .long local_label(misc_set_invalid) /* d3 imm  */
3780        .long local_label(misc_set_invalid) /* d4 odd_fixnum  */
3781        .long local_label(misc_set_invalid) /* d5 nil  */
3782        .long local_label(misc_set_invalid) /* d6 misc  */
3783        .long local_label(misc_set_s8) /* d7 s8  */
3784        .long local_label(misc_set_invalid) /* d8 even_fixnum  */
3785        .long local_label(misc_set_invalid) /* d9 cons  */
3786        .long local_label(misc_set_invalid) /* da nodeheader  */
3787        .long local_label(misc_set_invalid) /* db imm  */
3788        .long local_label(misc_set_invalid) /* dc odd_fixnum  */
3789        .long local_label(misc_set_invalid) /* dd nil  */
3790        .long local_label(misc_set_invalid) /* de misc  */
3791        .long local_label(misc_set_old_string) /* df (old) simple_base_string  */
3792        /* e0-ef  */
3793        .long local_label(misc_set_invalid) /* e0 even_fixnum  */
3794        .long local_label(misc_set_invalid) /* e1 cons  */
3795        .long local_label(misc_set_invalid) /* e2 nodeheader  */
3796        .long local_label(misc_set_invalid) /* e3 imm  */
3797        .long local_label(misc_set_invalid) /* e4 odd_fixnum  */
3798        .long local_label(misc_set_invalid) /* e5 nil  */
3799        .long local_label(misc_set_invalid) /* e6 misc  */
3800        .long local_label(misc_set_u16) /* e7 u16  */
3801        .long local_label(misc_set_invalid) /* e8 even_fixnum  */
3802        .long local_label(misc_set_invalid) /* e9 cons  */
3803        .long local_label(misc_set_invalid) /* ea nodeheader  */
3804        .long local_label(misc_set_invalid) /* eb imm  */
3805        .long local_label(misc_set_invalid) /* ec odd_fixnum  */
3806        .long local_label(misc_set_invalid) /* ed nil  */
3807        .long local_label(misc_set_invalid) /* ee misc  */
3808        .long local_label(misc_set_s16) /* ef s16  */
3809        /* f0-ff  */
3810        .long local_label(misc_set_invalid) /* f0 even_fixnum  */
3811        .long local_label(misc_set_invalid) /* f1 cons  */
3812        .long local_label(misc_set_invalid) /* f2 nodeheader  */
3813        .long local_label(misc_set_invalid) /* f3 imm  */
3814        .long local_label(misc_set_invalid) /* f4 odd_fixnum  */
3815        .long local_label(misc_set_invalid) /* f5 nil  */
3816        .long local_label(misc_set_invalid) /* f6 misc  */
3817        .long local_label(misc_set_double_float_vector) /* f7 df vector  */
3818        .long local_label(misc_set_invalid) /* f8 even_fixnum  */
3819        .long local_label(misc_set_invalid) /* f9 cons  */
3820        .long local_label(misc_set_invalid) /* fa nodeheader  */
3821        .long local_label(misc_set_invalid) /* fb imm  */
3822        .long local_label(misc_set_invalid) /* fc odd_fixnum  */
3823        .long local_label(misc_set_invalid) /* fd nil  */
3824        .long local_label(misc_set_invalid) /* fe misc  */
3825        .long local_label(misc_set_bit_vector) /* ff bit_vector  */
3826
3827local_label(misc_set_u32):       
3828        /* Either a non-negative fixnum, a positive one-digit bignum, */
3829        /* or a two-digit bignum whose sign-digit is 0 is ok.  */
3830        __(add imm0,arg_y,#misc_data_offset)
3831        __(test_fixnum(arg_z))
3832        __(bne local_label(set_not_fixnum_u32))
3833        __(tst arg_z,#0x80000000)
3834        __(bne local_label(set_bad))
3835        __(unbox_fixnum(imm1,arg_z))
3836local_label(set_set32):         
3837        __(str imm1,[arg_x,imm0])
3838        __(bx lr)
3839local_label(set_not_fixnum_u32):
3840        __(extract_lisptag(imm1,arg_z))
3841        __(cmp imm1,#tag_misc)
3842        __(bne local_label(set_bad))
3843        __(movc16(imm2,one_digit_bignum_header))
3844        __(getvheader(imm1,arg_z))
3845        __(cmp imm1,imm2)
3846        __(bne local_label(set_not_1_digit_u32))
3847        __(ldr imm1,[arg_z,#misc_data_offset])
3848        __(cmp imm1,#0)
3849        __(bge local_label(set_set32))
3850        __(b local_label(set_bad))
3851local_label(set_not_1_digit_u32):
3852        __(movc16(imm2,two_digit_bignum_header))
3853        __(cmp imm1,imm2)
3854        __(bne local_label(set_bad))
3855        __(vrefr(imm2,arg_z,1))
3856        __(vrefr(imm1,arg_z,0))
3857        __(cmp imm2,#0)
3858        __(beq local_label(set_set32))
3859local_label(set_bad):
3860        /* arg_z does not match the array-element-type of arg_x.  */
3861        __(mov arg_y,arg_z)
3862        __(mov arg_z,arg_x)
3863        __(mov arg_x,#XNOTELT)
3864        __(set_nargs(3))
3865        __(b _SPksignalerr)
3866local_label(misc_set_fixnum_vector):   
3867        __(add imm0,arg_z,#misc_data_offset)
3868        __(test_fixnum(arg_z))
3869        __(bne local_label(set_bad))
3870        __(unbox_fixnum(imm1,arg_z))
3871        __(str imm1,[arg_x,imm0])
3872        __(bx lr)
3873local_label(misc_set_new_string):   
3874        __(add imm0,arg_z,#misc_data_offset)
3875        __(extract_lowbyte(imm2,arg_z))
3876        __(cmp imm2,#subtag_character)
3877        __(bne local_label(set_bad))
3878        __(unbox_character(imm1,arg_z))
3879        __(str imm1,[arg_x,imm0])
3880        __(bx lr)
3881local_label(misc_set_s32):
3882        __(add imm0,arg_z,#misc_data_offset)
3883        __(test_fixnum(arg_z))
3884        __(moveq imm1,arg_z,asr #fixnumshift)
3885        __(beq local_label(set_set32))
3886        __(extract_lisptag(imm2,arg_z))
3887        __(cmp imm2,#tag_misc)
3888        __(bne local_label(set_bad))
3889        __(movc16(imm1,one_digit_bignum_header))
3890        __(getvheader(imm2,arg_z))
3891        __(cmp imm2,imm1)
3892        __(vrefr(imm1,arg_z,0))
3893        __(beq local_label(set_set32))
3894        __(b local_label(set_bad))
3895local_label(misc_set_single_float_vector):
3896        __(add imm0,arg_z,#misc_data_offset)
3897        __(extract_typecode(imm2,arg_z))
3898        __(cmp imm2,#subtag_single_float)
3899        __(bne local_label(set_bad))
3900        __(ldr imm1,[arg_z,#single_float.value])
3901        __(str imm1,[arg_x,imm0])
3902        __(bx lr)
3903local_label(misc_set_u8):               
3904        __(mov imm0,arg_y,lsr #2)
3905        __(add imm0,imm0,#misc_data_offset)
3906        __(mov imm2,#~(0xff<<fixnumshift))
3907        __(tst arg_z,imm2)
3908        __(bne local_label(set_bad))
3909        __(unbox_fixnum(imm1,arg_z))
3910        __(strb imm1,[arg_x,imm0])
3911        __(bx lr)
3912local_label(misc_set_old_string):
3913        __(mov imm0,arg_y,lsr #2)
3914        __(add imm0,imm0,#misc_data_offset)
3915        __(extract_lowbyte(imm2,arg_z))
3916        __(cmp imm2,#subtag_character)
3917        __(unbox_character(imm1,arg_z))
3918        __(bne local_label(set_bad))
3919        __(strb imm1,[arg_x,imm0])
3920        __(bx lr)
3921local_label(misc_set_s8):
3922        __(mov imm0,arg_y,lsr #2)
3923        __(add imm0,imm0,#misc_data_offset)
3924        __(test_fixnum(arg_z))
3925        __(bne local_label(set_bad))
3926        __(unbox_fixnum(imm1,arg_z))
3927        __(mov imm2,imm1,lsl #32-8)
3928        __(cmp imm1,imm2,asr #32-8)
3929        __(bne local_label(set_bad))
3930        __(strb imm1,[arg_x,imm0])
3931        __(bx lr)
3932local_label(misc_set_u16):         
3933        __(mov imm0,arg_y,lsr #1)
3934        __(add imm0,imm0,#misc_data_offset)
3935        __(test_fixnum(arg_z))
3936        __(bne local_label(set_bad))
3937        __(unbox_fixnum(imm1,arg_z))
3938        __(mov imm2,imm1,lsl #16)
3939        __(cmp imm1,imm2,lsr #16)
3940        __(bne local_label(set_bad))
3941        __(strh imm1,[arg_x,imm0])
3942        __(bx lr)
3943local_label(misc_set_s16):
3944        __(mov imm0,arg_y,lsr #1)
3945        __(add imm0,imm0,#misc_data_offset)
3946        __(test_fixnum(arg_z))
3947        __(bne local_label(set_bad))
3948        __(unbox_fixnum(imm1,arg_z))
3949        __(mov imm2,imm1,lsl #16)
3950        __(cmp imm1,imm2,asr #16)
3951        __(bne local_label(set_bad))
3952        __(strh imm1,[arg_x,imm0])
3953        __(bx lr)
3954local_label(misc_set_bit_vector):
3955        __(bics imm0,arg_z,#fixnumone)
3956        __(bne local_label(set_bad))
3957        __(mov imm2,#31)
3958        __(and imm2,imm1,arg_y,lsr #2)
3959        __(mov imm1,#1)
3960        __(mov imm1,imm1,lsl imm2)
3961        __(mov imm0,arg_y,lsr #fixnumshift+5)
3962        __(mov imm0,imm0,lsl #2)
3963        __(add imm0,imm0,#misc_data_offset)
3964        __(cmp arg_z,#0)
3965        __(ldr imm2,[arg_x,imm0])
3966        __(orrne imm2,imm2,imm1)
3967        __(biceq imm2,imm2,imm1)
3968        __(str imm2,[arg_x,imm0])
3969        __(bx lr)
3970
3971local_label(misc_set_double_float_vector):
3972        __(extract_subtag(imm2,arg_z))
3973        __(cmp imm2,#subtag_double_float)
3974        __(bne local_label(set_bad))
3975        __(ldrd imm0,imm1,[arg_z,#misc_dfloat_offset])
3976        __(mov imm2,arg_y,lsl #1)
3977        __(add imm2,imm2,#misc_dfloat_offset)
3978        __(strd imm0,imm1,[arg_x,imm2])
3979        __(bx lr)
3980local_label(misc_set_invalid): 
3981        __(mov temp0,#XSETBADVEC)       
3982        __(set_nargs(4))
3983        __(vpush1(temp0))
3984        __(b _SPksignalerr)               
3985
3986       
3987/* imm2: (tstack-consed) target catch frame, imm0: count of intervening  */
3988/* frames. If target isn't a multiple-value receiver, discard extra values */
3989/* (less hair, maybe.)  */
3990C(_throw_found):
3991pushdef(`__',`
3992        .word 0
3993        ')       
3994        __(ldr imm1,[imm2,#catch_frame.mvflag])
3995        __(cmpri(imm1,0))
3996        __(cmpri(cr1,nargs,0))
3997        __(mov fn,#0)
3998        __(add imm1,vsp,nargs)
3999        __(add imm1,[imm1,#-node_size])
4000        __(bne local_label(_throw_all_values))
4001        __(set_nargs(1))
4002        __(beq cr1,local_label(_throw_default_1_val))
4003        __(mov vsp,imm1)
4004        __(b local_label(_throw_all_values))
4005local_label(_throw_default_1_val):
4006        __(mov imm4,#nil_value)
4007        __(vpush1(imm4))
4008local_label(_throw_all_values):
4009        __(bl _SPnthrowvalues)
4010        __(ldr imm3,[rcontext,#tcr.catch_top])
4011        __(ldr imm1,[rcontext,#tcr.db_link])
4012        __(ldr imm0,[imm3,#catch_frame.db_link])
4013        __(ldr imm4,[imm3,#catch_frame.mvflag])
4014        __(cmpr(imm0,imm1))
4015        __(cmpri(cr1,imm4,0))
4016        __(add tsp,[imm3,#-((tsp_frame.fixed_overhead+fulltag_misc))])
4017        __(beq local_label(_throw_dont_unbind))
4018        __(bl _SPunbind_to)
4019local_label(_throw_dont_unbind):
4020        __(add imm0,vsp,nargs)
4021        __(cmpri(nargs,0))
4022        __(ldr imm1,[imm3,#catch_frame.csp])
4023        __(ldr imm1,[imm1,#lisp_frame.savevsp])
4024        __(bne cr1,local_label(_throw_multiple))
4025        /* Catcher expects single value in arg_z  */
4026        __(ldr arg_z,[imm0,#-node_size])
4027        __(b local_label(_throw_pushed_values))
4028local_label(_throw_multiple):
4029        __(beq local_label(_throw_pushed_values))
4030        __(mov imm2,nargs)
4031local_label(_throw_mvloop):
4032        __(sub imm2,imm2,fixnum_one)
4033        __(cmpri(imm2,0))
4034        __(ldru(temp0,-node_size(imm0)))
4035        __(push(temp0,imm1))
4036        __(bgt local_label(_throw_mvloop))
4037local_label(_throw_pushed_values):
4038        __(mov vsp,imm1)
4039        __(ldr imm1,[imm3,#catch_frame.xframe])
4040        __(str(imm1,tcr.xframe(rcontext)))
4041        __(ldr sp,[imm3,#catch_frame.csp])
4042        __(ldr fn,[sp,#lisp_frame.savefn])
4043        __(ldr loc_pc,[sp,#lisp_frame.savelr])
4044        __(discard_lisp_frame())
4045        __(mtlr loc_pc)
4046        __(restore_catch_nvrs(imm3))
4047        __(ldr imm3,[imm3,#catch_frame.link])
4048        __(str(imm3,tcr.catch_top(rcontext)))
4049        __(unlink(tsp))
4050        __(bx lr)
4051popdef(`__')
4052
4053C(nthrow1v):   
4054local_label(_nthrow1v_nextframe):
4055        __(subs temp2,temp2,#fixnum_one)
4056        __(ldr temp0,[rcontext,#tcr.catch_top])
4057        __(ldr imm1,[rcontext,#tcr.db_link])
4058        __(set_nargs(1))
4059        __(blt local_label(_nthrow1v_done))
4060        __(ldr arg_y,[temp0,#catch_frame.link])
4061        __(ldr imm0,[temp0,#catch_frame.db_link])
4062        __(cmp imm0,imm1)
4063        __(str arg_y,[rcontext,#tcr.catch_top])
4064        __(ldr arg_y,[temp0,#catch_frame.xframe])
4065        __(str arg_y,[rcontext,#tcr.xframe])
4066        __(beq local_label(_nthrow1v_dont_unbind))
4067        __(do_unbind_to(imm1,temp1,arg_x,arg_y))
4068local_label(_nthrow1v_dont_unbind):
4069        __(ldr temp1,[temp0,#catch_frame.catch_tag])
4070        __(cmp temp1,#unbound_marker)  /* unwind-protect ?  */
4071        __(beq local_label(_nthrow1v_do_unwind))
4072        /* A catch frame.  If the last one, restore context from there.  */
4073        __(cmp temp2,#0)
4074        __(ldreq vsp,[sp,#catch_frame.size+lisp_frame.savevsp])
4075        __(add sp,sp,#catch_frame.size+lisp_frame.size)
4076        __(b local_label(_nthrow1v_nextframe))
4077local_label(_nthrow1v_do_unwind):
4078        /* This is harder, but not as hard (not as much BLTing) as the  */
4079        /* multiple-value case.  */
4080        /* Save our caller's LR and FN in the csp frame created by the unwind-  */
4081        /* protect.  (Clever, eh ?)  */
4082        __(add sp,sp,#catch_frame.size)
4083        /* swp is deprecated on ARMv6+.  It's not useful as a basis
4084           for synchronization, but that's not why we're using it here. */
4085        __(mov imm1,#0)
4086        __(mov temp0,sp)
4087        __(mov imm0,#3<<num_subtag_bits)
4088        __(orr imm0,imm0,#subtag_simple_vector)
4089        __(stmdb sp!,{imm0,imm1,arg_z,temp2})
4090        __(add imm0,temp0,#lisp_frame.savelr)
4091        __(swp lr,lr,[imm0])
4092        __(ldr nfn,[temp0,#lisp_frame.savefn])
4093        __(str fn,[temp0,#lisp_frame.savefn])
4094        __(ldr vsp,[temp0,#lisp_frame.savevsp])
4095        __(mov fn,nfn)
4096        __(str imm1,[rcontext,#tcr.unwinding])
4097        __(blx lr)
4098        __(mov imm1,#1)
4099        __(ldr arg_z,[sp,#8])
4100        __(str imm1,[rcontext,#tcr.unwinding])
4101        __(ldr temp2,[sp,#12])
4102        __(add sp,sp,#4*node_size)
4103        __(restore_lisp_frame(imm0))
4104        __(b local_label(_nthrow1v_nextframe))
4105local_label(_nthrow1v_done):
4106        __(mov imm0,#0)
4107        __(str imm0,[rcontext,#tcr.unwinding])
4108        /* nargs has an undefined value here, so we can clobber it while */
4109        /* polling for a deferred interrupt  */
4110        __(check_pending_interrupt(nargs))
4111        __(bx lr)
4112       
4113       
4114        _endfile
Note: See TracBrowser for help on using the repository browser.