source: trunk/source/lisp-kernel/arm-spentry.s @ 14347

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

In write-barrier code, return without store-conditional if the
refbit's already set.

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