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

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

Ensure that stack pointer is aligned on an 8-byte boundary when calling
into lisp (the iOS ABI doesn't ensure this.)

File size: 145.7 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)
7190:      __(ldrex imm2,[temp0])
720        __(orr imm2,imm2,imm1)
721        __(strex imm0,imm2,[temp0])
722        __(cmp imm0,#0)
723        __(bne 0b)       
724        __(bx lr)
725
726
727        .globl C(egc_rplacd)
728_spentry(rplacd)
729C(egc_rplacd):
730        __(cmp arg_z,arg_y)
731        __(_rplacd(arg_y,arg_z))
732        __(bxlo lr)
733        __(ref_global(temp0,ref_base))
734        __(sub imm0,arg_y,temp0)
735        __(mov imm0,imm0,lsr #dnode_shift)
736        __(ref_global(imm1,oldspace_dnode_count))
737        __(cmp imm0,imm1)
738        __(bxhs lr)
739        __(and imm2,imm0,#31)
740        __(mov imm1,#0x80000000)
741        __(mov imm1,imm1,lsr imm2)
742        __(mov imm0,imm0,lsr #bitmap_shift)
743        __(ref_global(temp0,refbits))
744        __(add temp0,temp0,imm0,lsl #word_shift)
7450:      __(ldrex imm2,[temp0])
746        __(orr imm2,imm2,imm1)
747        __(strex imm0,imm2,[temp0])
748        __(cmp imm0,#0)
749        __(bne 0b)       
750        __(bx lr)
751       
752
753/* Storing into a gvector can be handled the same way as storing into a CONS. */
754
755        .globl C(egc_gvset)
756_spentry(gvset)
757C(egc_gvset):
758        __(cmp arg_z,arg_x)
759        __(add imm0,arg_y,#misc_data_offset)
760        __(str arg_z,[arg_x,imm0])
761        __(bxlo lr)               
762        __(add imm0,imm0,arg_x)
763        __(ref_global(temp0,ref_base))
764        __(sub imm0,imm0,temp0)
765        __(mov imm0,imm0,lsr #dnode_shift)
766        __(ref_global(imm1,oldspace_dnode_count))
767        __(cmp imm0,imm1)
768        __(bxhs lr)
769        __(and imm2,imm0,#31)
770        __(mov imm1,#0x80000000)
771        __(mov imm1,imm1,lsr imm2)
772        __(mov imm0,imm0,lsr #bitmap_shift)
773        __(ref_global(temp0,refbits))
774        __(add temp0,temp0,imm0,lsl #word_shift)
7750:      __(ldrex imm2,[temp0])
776        __(orr imm2,imm2,imm1)
777        __(strex imm0,imm2,[temp0])
778        __(cmp imm0,#0)
779        __(bne 0b)       
780        __(bx lr)
781
782       
783/* This is a special case of storing into a gvector: if we need to memoize  */
784/* the store, record the address of the hash-table vector in the refmap,  */
785/* as well. */
786        .globl C(egc_set_hash_key)       
787_spentry(set_hash_key)
788C(egc_set_hash_key):
789        __(cmp arg_z,arg_x)
790        __(add imm0,arg_y,#misc_data_offset)
791        __(str arg_z,[arg_x,imm0])
792        __(bxlo lr)
793        __(add imm0,imm0,arg_x)
794        __(ref_global(temp0,ref_base))
795        __(sub imm0,imm0,temp0)
796        __(mov imm0,imm0,lsr #dnode_shift)
797        __(ref_global(imm1,oldspace_dnode_count))
798        __(cmp imm0,imm1)
799        __(bxhs lr)
800        __(and imm2,imm0,#31)
801        __(mov imm1,#0x80000000)
802        __(mov imm1,imm1,lsr imm2)
803        __(mov imm0,imm0,lsr #bitmap_shift)
804        __(ref_global(temp0,refbits))
805        __(add temp0,temp0,imm0,lsl #word_shift)
8060:      __(ldrex imm2,[temp0])
807        __(orr imm2,imm2,imm1)
808        __(strex imm0,imm2,[temp0])
809        __(cmp imm0,#0)
810        __(bne 0b)       
811/* Now need to ensure that the hash table itself is in the refmap; we
812   know that it's in bounds, etc. */
813        __(ref_global(temp0,ref_base))
814        __(sub imm0,arg_x,temp0)
815        __(mov imm0,imm0,lsr #dnode_shift)
816        __(and imm2,imm0,#31)
817        __(mov imm1,#0x80000000)
818        __(mov imm1,imm1,lsr imm2)
819        __(mov imm0,imm0,lsr #bitmap_shift)
820        __(ref_global(temp0,refbits))
821        __(add temp0,temp0,imm0,lsl #word_shift)
8221:      __(ldrex imm2,[temp0])
823        __(orr imm2,imm2,imm1)
824        __(strex imm0,imm2,[temp0])
825        __(cmp imm0,#0)
826        __(bne 1b)       
827        __(bx lr)
828       
829
830/*
831   Interrupt handling (in pc_luser_xp()) notes: 
832   If we are in this function and before the test which follows the
833   conditional (at egc_store_node_conditional), or at that test
834   and cr0`eq' is clear, pc_luser_xp() should just let this continue
835   (we either haven't done the store conditional yet, or got a
836   possibly transient failure.)  If we're at that test and the
837   cr0`EQ' bit is set, then the conditional store succeeded and
838   we have to atomically memoize the possible intergenerational
839   reference.  Note that the local labels 4 and 5 are in the
840   body of the next subprim (and at or beyond 'egc_write_barrier_end').
841
842   N.B: it's not possible to really understand what's going on just
843   by the state of the cr0`eq' bit.  A transient failure in the
844   conditional stores that handle memoization might clear cr0`eq'
845   without having completed the memoization.
846*/
847
848            .globl C(egc_store_node_conditional)
849            .globl C(egc_write_barrier_end)
850_spentry(store_node_conditional)
851C(egc_store_node_conditional):
852        __(vpop1(temp0))
853         
8541:      __(unbox_fixnum(imm2,temp0))
855        __(add imm2,imm2,arg_x)
856        __(ldrex temp1,[imm2])
857        __(cmp temp1,arg_y)
858        __(bne 5f)
859        __(strex imm0,arg_z,[imm2])
860        .globl C(egc_store_node_conditional_test)
861C(egc_store_node_conditional_test): 
862        __(cmp imm0,#0)
863        __(bne 1b)
864        __(cmp arg_z,arg_x)
865        __(blo 4f)
866
867        __(ref_global(imm0,ref_base))
868        __(ref_global(imm1,oldspace_dnode_count))
869        __(sub imm0,imm2,imm0)
870        __(mov imm0,imm0,lsr #dnode_shift)
871        __(cmp imm0,imm1)
872        __(bhs 4f)
873        __(and imm1,imm0,#31)
874        __(mov arg_x,#0x80000000)
875        __(mov imm1,arg_x,lsr imm1)
876        __(ref_global(temp0,refbits))
877        __(mov imm0,imm0,lsr #bitmap_shift)
878        __(add temp0,temp0,imm0,lsl #word_shift)
8792:      __(ldrex imm2,[temp0])
880        __(orr imm2,imm2,imm1)
881        __(strex imm0,imm2,[temp0])
882        .globl C(egc_set_hash_key_conditional_test)
883C(egc_set_hash_key_conditional_test): 
884        __(cmp imm0,#0)
885        __(bne 2b)
886        __(b 4f)
887 
888/* arg_z = new value, arg_y = expected old value, arg_x = hash-vector,
889    vsp`0' = (boxed) byte-offset
890    Interrupt-related issues are as in store_node_conditional, but
891    we have to do more work to actually do the memoization.*/
892_spentry(set_hash_key_conditional)
893        .globl C(egc_set_hash_key_conditional)
894C(egc_set_hash_key_conditional):
895        __(vpop1(imm1))
896        __(unbox_fixnum(imm1,imm1))
8970:      __(add imm2,arg_x,imm1)
898        __(ldrex temp1,[imm2])
899        __(cmp temp1,arg_y)
900        __(bne 5f)
901        __(strex imm0,arg_z,[imm2])
902        __(cmp imm0,#0)
903        __(bne 0b)
904        __(cmp arg_z,arg_x)
905        __(blo 4f)
906        __(ref_global(temp0,ref_base))
907        __(sub imm0,imm2,temp0)
908        __(mov imm0,imm0,lsr #dnode_shift)
909        __(ref_global(imm1,oldspace_dnode_count))
910        __(cmp imm0,imm1)
911        __(bhs 4f)
912        __(and imm2,imm0,#31)
913        __(mov imm1,#0x80000000)
914        __(mov imm1,imm1,lsr imm2)
915        __(mov imm0,imm0,lsr #bitmap_shift)
916        __(ref_global(temp0,refbits))
917        __(add temp0,temp0,imm0,lsl #word_shift)
9181:      __(ldrex imm2,[temp0])
919        __(orr imm2,imm2,imm1)
920        __(strex imm0,imm2,[temp0])
921        __(cmp imm0,#0)
922        __(bne 1b)       
923/* Now need to ensure that the hash table itself is in the refmap; we
924   know that it's in bounds, etc. */
925        __(ref_global(temp0,ref_base))
926        __(sub imm0,arg_x,temp0)
927        __(mov imm0,imm0,lsr #dnode_shift)
928        __(and imm2,imm0,#31)
929        __(mov imm1,#0x80000000)
930        __(mov imm1,imm1,lsr imm2)
931        __(mov imm0,imm0,lsr #bitmap_shift)
932        __(ref_global(temp0,refbits))
933        __(add temp0,temp0,imm0,lsl #word_shift)
9341:      __(ldrex imm2,[temp0])
935        __(orr imm2,imm2,imm1)
936        __(strex imm0,imm2,[temp0])
937        __(cmp imm0,#0)
938        __(bne 1b)       
939C(egc_write_barrier_end):
9404:      __(mov arg_z,#nil_value)
941        __(add arg_z,arg_z,#t_offset)
942        __(bx lr)
9435:      __(clrex)
944        __(mov arg_z,#nil_value)
945        __(bx lr)
946
947
948
949
950       
951/* We always have to create a stack frame (even if nargs is 0), so the compiler  */
952/* doesn't get confused.  */
953_spentry(stkconslist)
954        __(mov arg_z,#nil_value)
955C(stkconslist_star):           
956        __(mov temp2,nargs,lsl #1)
957        __(add temp2,temp2,#node_size)
958        __(mov imm0,temp2,lsl #num_subtag_bits-word_shift)
959        __(add temp2,temp2,#node_size)
960        __(orr imm0,imm0,#subtag_u32_vector)
961        __(stack_allocate_zeroed_ivector(imm0,temp2))
962        __(mov imm0,#subtag_simple_vector)
963        __(strb imm0,[sp,#0])
964        __(add imm1,sp,#dnode_size+fulltag_cons)
965        __(cmp nargs,#0)
966        __(b 4f)
9671:      __(vpop1(temp0))
968        __(_rplaca(imm1,temp0))
969        __(_rplacd(imm1,arg_z))
970        __(mov arg_z,imm1)
971        __(add imm1,imm1,#cons.size)
972        __(subs nargs,nargs,#node_size)
9734:
974        __(bne 1b)
975        __(bx lr)
976 
977/* do list*: last arg in arg_z, all others vpushed,  */
978/* nargs set to #args vpushed.  */
979_spentry(stkconslist_star)
980        __(b C(stkconslist_star))
981
982/* Make a stack-consed simple-vector out of the NARGS objects  */
983/* on top of the vstack; return it in arg_z.  */
984_spentry(mkstackv)
985        __(dnode_align(imm1,nargs,node_size))
986        __(mov imm0,nargs,lsl #num_subtag_bits-fixnumshift)
987        __(orr imm0,imm0,#subtag_u32_vector)
988        __(stack_allocate_zeroed_ivector(imm0,imm1))
989        __(mov imm0,#subtag_simple_vector)
990        __(strb imm0,[sp,#0])
991        __(add arg_z,sp,#fulltag_misc)
992        __(add imm0,arg_z,#misc_data_offset)
993        __(add imm1,imm0,nargs)
994        __(b 4f)
9953:      __(vpop1(arg_y))
996        __(str arg_y,[imm1,#-node_size]!)
997        __(sub nargs,nargs,#node_size)
9984:      __(cmp nargs,#0)
999        __(bne 3b)
1000        __(bx lr)
1001       
1002_spentry(setqsym)
1003        __(ldr imm0,[arg_y,#symbol.flags])
1004        __(tst imm0,#sym_vbit_const_mask)
1005        __(beq _SPspecset)
1006        __(mov arg_z,arg_y)
1007        __(mov arg_y,#XCONST)
1008        __(set_nargs(2))
1009        __(b _SPksignalerr)
1010
1011
1012
1013_spentry(progvsave)
1014        __(b (C(progvsave)))
1015 
1016       
1017/* Allocate a uvector on the  stack.  (Push a frame on the stack and  */
1018/* heap-cons the object if there's no room on the stack.)  */
1019_spentry(stack_misc_alloc)
1020        __(tst arg_y,#unsigned_byte_24_mask)
1021        __(uuo_error_reg_not_xtype(ne,arg_y,xtype_unsigned_byte_24))
1022        __(unbox_fixnum(imm0,arg_z))
1023        __(extract_fulltag(imm1,imm0))
1024        __(cmp imm1,#fulltag_nodeheader)
1025        __(bne 1f)
1026        __(dnode_align(imm1,arg_y,node_size))
1027        __(cmp imm1,#stack_alloc_limit)
1028        __(bhs stack_misc_alloc_no_room)
1029        __(mov imm0,#subtag_u32_vector)
1030        __(orr imm0,imm0,arg_y,lsl #num_subtag_bits-fixnumshift)
1031        __(mov temp0,#stack_alloc_marker)
1032        __(mov temp1,sp)
1033        __(stack_allocate_zeroed_ivector(imm0,imm1))
1034        __(unbox_fixnum(imm0,arg_z))
1035        __(strb imm0,[sp])
1036        __(add arg_z,sp,#fulltag_misc)
1037        __(stmdb sp!,{temp0,temp1})
1038        __(bx lr)
10391:      __(mov imm0,arg_y,lsl #num_subtag_bits-fixnumshift)
1040        __(orr imm0,imm0,arg_z,lsr #fixnumshift)
1041        __(cmp arg_z,#max_32_bit_ivector_subtag<<fixnumshift)
1042        __(movle imm1,arg_y)
1043        __(ble 8f)
1044        __(cmp arg_z,#max_8_bit_ivector_subtag<<fixnumshift)
1045        __(movle imm1,arg_y,lsr #fixnumshift)
1046        __(ble 8f)
1047        __(cmp arg_z,#max_16_bit_ivector_subtag<<fixnumshift)
1048        __(movle imm1,arg_y,lsr #1)
1049        __(ble 8f)
1050        __(cmp arg_z,#subtag_double_float)
1051        __(moveq imm1,arg_y,lsl #1)
1052        __(addeq imm1,imm1,#node_size)
1053        __(addne imm1,arg_y,#7<<fixnumshift)
1054        __(movne imm1,imm1,lsr#3+fixnumshift)
10558:      __(dnode_align(imm1,imm1,node_size))
1056        __(cmp imm1,#stack_alloc_limit)
1057        __(bhs stack_misc_alloc_no_room)
1058        __(mov temp0,#stack_alloc_marker)
1059        __(mov temp1,sp)
1060        __(stack_allocate_zeroed_ivector(imm0,imm1))
1061        __(add arg_z,sp,#fulltag_misc)
1062        __(stmdb sp!,{temp0,temp1})
1063        __(bx lr)
1064
1065
1066
1067
1068/* subtype (boxed, of course) is vpushed, followed by nargs bytes worth of  */
1069/* initial-contents.  Note that this can be used to cons any type of initialized  */
1070/* node-header'ed misc object (symbols, closures, ...) as well as vector-like  */
1071/* objects.  */
1072
1073_spentry(gvector)
1074        __(sub nargs,nargs,#node_size)
1075        __(ldr arg_z,[vsp,nargs])
1076        __(unbox_fixnum(imm0,arg_z))
1077        __(orr imm0,imm0,nargs,lsl #num_subtag_bits-fixnum_shift)
1078        __(dnode_align(imm1,nargs,node_size))
1079        __(Misc_Alloc(arg_z,imm0,imm1))
1080        __(mov imm1,nargs)
1081        __(add imm2,imm1,#misc_data_offset)
1082        __(b 2f)
10831:
1084        __(str temp0,[arg_z,imm2])
10852:
1086        __(sub imm1,imm1,#node_size)
1087        __(cmp imm1,#0)
1088        __(sub imm2,imm2,#node_size)
1089        __(vpop1(temp0))        /* Note the intentional fencepost: */
1090                                /* discard the subtype as well.  */
1091        __(bge 1b)
1092        __(bx lr)
1093
1094_spentry(fitvals)
1095        __(subs imm0,imm0,nargs)
1096        __(mov imm1,#nil_value)
1097        __(sublt vsp,vsp,imm0)
1098        __(bxlt lr)
1099        __(b 2f)
11001:
1101        __(subs imm0,imm0,#node_size)
1102        __(vpush1(imm1))       
1103        __(add nargs,nargs,#node_size)
11042:
1105        __(bne 1b)
1106        __(bx lr)
1107
1108
1109_spentry(nthvalue)
1110        __(add imm0,vsp,nargs)
1111        __(ldr imm1,[imm0,#0])
1112        __(cmp imm1,nargs) /*  do unsigned compare:  if (n < 0) => nil.  */
1113        __(mov arg_z,#nil_value)
1114        __(rsb imm1,imm1,#0)
1115        __(sub imm1,imm1,#node_size)
1116        __(ldrlo arg_z,[imm0,imm1])
1117        __(add vsp,imm0,#node_size)
1118        __(bx lr)
1119
1120/* Provide default (NIL) values for &optional arguments; imm0 is  */
1121/* the (fixnum) upper limit on the total of required and &optional  */
1122/* arguments.  nargs is preserved, all arguments wind up on the  */
1123/* vstack.  */
1124_spentry(default_optional_args)
1125        __(vpush_argregs())
1126        __(cmp nargs,imm0)
1127        __(mov arg_z,#nil_value)
1128        __(mov imm1,nargs)
1129        __(bxhs lr)
11301:
1131        __(add imm1,imm1,#fixnum_one)
1132        __(cmp imm1,imm0)
1133        __(vpush1(arg_z))
1134        __(bne 1b)
1135        __(bx lr)
1136
1137/* Indicate whether &optional arguments were actually supplied.  nargs  */
1138/* contains the actual arg count (minus the number of required args);  */
1139/* imm0 contains the number of &optional args in the lambda list.  */
1140/* Note that nargs may be > imm0 if &rest/&key is involved.  */
1141_spentry(opt_supplied_p)
1142        __(mov imm1,#0)
1143        __(mov arg_x,#nil_value)
1144        __(add arg_x,arg_x,#t_offset)       
11451:     
1146        /* (vpush (< imm1 nargs))  */
1147        __(cmp imm1,nargs)
1148        __(add imm1,imm1,#fixnumone)
1149        __(subeq arg_x,arg_x,#t_offset)
1150        __(vpush1(arg_x))
1151        __(cmp imm1,imm0)
1152        __(bne 1b)
1153        __(bx lr)
1154
1155/* Cons a list of length nargs  and vpush it.  */
1156/* Use this entry point to heap-cons a simple &rest arg.  */
1157_spentry(heap_rest_arg)
1158        __(vpush_argregs())
1159        __(movs imm1,nargs)
1160        __(mov arg_z,#nil_value)
1161        __(b 2f)
11621:
1163        __(vpop1(arg_y))
1164        __(Cons(arg_z,arg_y,arg_z))
1165        __(subs imm1,imm1,#fixnum_one)
11662:
1167        __(bne 1b)
1168        __(vpush1(arg_z))
1169        __(bx lr)
1170
1171 
1172/* And this entry point when the argument registers haven't yet been  */
1173/* vpushed (as is typically the case when required/&rest but no  */
1174/* &optional/&key.)  */
1175_spentry(req_heap_rest_arg)
1176        __(vpush_argregs())
1177        __(subs imm1,nargs,imm0)
1178        __(mov arg_z,#nil_value)
1179        __(b 2f)
11801:
1181        __(vpop1(arg_y))
1182        __(Cons(arg_z,arg_y,arg_z))
1183        __(subs imm1,imm1,#fixnum_one)
11842:
1185        __(bgt 1b)
1186        __(vpush1(arg_z))
1187        __(bx lr)
1188
1189/* Here where argregs already pushed */
1190_spentry(heap_cons_rest_arg)
1191        __(subs imm1,nargs,imm0)
1192        __(mov arg_z,#nil_value)
1193        __(b 2f)
11941:
1195        __(vpop1(arg_y))
1196        __(Cons(arg_z,arg_y,arg_z))
1197        __(subs imm1,imm1,#fixnum_one)
11982:
1199        __(bgt 1b)
1200        __(vpush1(arg_z))
1201        __(bx lr)
1202
1203
1204_spentry(check_fpu_exception)
1205        __(fmrx imm0,fpscr)
1206        __(mov imm2,imm0)
1207        __(ldr imm1,[rcontext,#tcr.lisp_fpscr])
1208        __(ands imm0,imm0,imm1,lsr #8)
1209        __(bxeq lr)
1210        __(bic imm2,imm2,#0xff)
1211        __(fmxr fpscr,imm2)
1212        __(build_lisp_frame(imm2))
1213        __(mov imm2,#34<<fixnumshift)
1214        __(movc16(imm1,make_header(33,subtag_u32_vector)))
1215        __(stack_allocate_ivector(imm1,imm2))
1216        __(add arg_z,sp,#fulltag_misc)
1217        __(str imm0,[arg_z,#misc_data_offset])
1218        __(add imm0,sp,#dnode_size)
1219        __(fstmiad imm0,{d0-d15})
1220        __(ldr imm1,[lr,#-8])
1221        __(uuo_error_fpu_exception(al,arg_z,imm1))
1222        __(add imm0,sp,#dnode_size)
1223        __(fldmiad imm0,{d0-d15})
1224        __(add sp,sp,#34<<fixnumshift)
1225        __(return_lisp_frame(imm0))
1226
1227_spentry(discard_stack_object)
1228        new_local_labels()       
1229        __(ldr imm0,[sp,#0])
1230        __(cmp imm0,#stack_alloc_marker)
1231        __(ldreq sp,[sp,#node_size])
1232        __(bxeq lr)
1233        __(cmp imm0,#lisp_frame_marker)
1234        __(extract_fulltag(imm1,imm0))
1235        __(addeq sp,sp,#lisp_frame.size)
1236        __(bxeq lr)
1237        __(cmp imm1,#fulltag_immheader)
1238        __(and imm1,imm0,#subtag_mask)
1239        __(bic imm0,imm0,#subtag_mask)
1240        __(beq local_label(ivector))
1241local_label(word):
1242        __(mov imm0,imm0,lsr #num_subtag_bits-word_shift)
1243local_label(out):       
1244        __(dnode_align(imm0,imm0,node_size))
1245        __(add sp,sp,imm0)
1246        __(bx lr)
1247local_label(ivector):     
1248        __(cmp imm1,#max_32_bit_ivector_subtag)
1249        __(bls local_label(word))       
1250        __(cmp imm1,#max_8_bit_ivector_subtag)
1251        __(movls imm0,imm0,lsr #num_subtag_bits)
1252        __(bls local_label(out))
1253        __(cmp imm1,#max_16_bit_ivector_subtag)
1254        __(movls imm0,imm0,lsr #num_subtag_bits-1)
1255        __(bls local_label(out))
1256        __(cmp imm1,#subtag_bit_vector)
1257        __(moveq imm0,imm0,lsr #num_subtag_bits)
1258        __(addeq imm0,imm0,#7)
1259        __(moveq imm0,imm0,lsr #3)
1260        __(beq local_label(out))
1261        /* The infamous 'stack-consed double-float vector' case */
1262        __(mov imm0,imm0,lsr #num_subtag_bits-dnode_shift)
1263        __(b local_label(out))
1264
1265
1266       
1267/* Signal an error synchronously, via %ERR-DISP.  */
1268/* If %ERR-DISP isn't fbound, it'd be nice to print a message  */
1269/* on the C runtime stderr.  */
1270 
1271_spentry(ksignalerr)
1272        __(ref_nrs_symbol(fname,errdisp,imm0))
1273        __(jump_fname)
1274
1275/* As in the heap-consed cases, only stack-cons the &rest arg  */
1276_spentry(stack_rest_arg)
1277        __(mov imm0,#0)
1278        __(vpush_argregs())
1279        __(b _SPstack_cons_rest_arg)
1280
1281_spentry(req_stack_rest_arg)
1282        __(vpush_argregs())
1283        __(b _SPstack_cons_rest_arg)
1284
1285_spentry(stack_cons_rest_arg)
1286        __(subs imm1,nargs,imm0)
1287        __(mov arg_z,#nil_value)
1288        __(ble 2f)  /* always temp-push something.  */
1289        __(mov temp0,imm1)
1290        __(add imm1,imm1,imm1)
1291        __(add imm1,imm1,#node_size)
1292        __(dnode_align(imm0,imm1,node_size))
1293        __(mov imm1,imm1,lsl #num_subtag_bits-fixnumshift)
1294        __(orr imm1,imm1,#subtag_u32_vector)
1295        __(cmp imm0,#stack_alloc_limit)
1296        __(bge 3f)
1297        __(stack_allocate_zeroed_ivector(imm1,imm0))
1298        __(mov imm0,#subtag_simple_vector)
1299        __(strb imm0,[sp])
1300        __(add imm0,sp,#dnode_size+fulltag_cons)
13011:
1302        __(subs temp0,temp0,#fixnumone)
1303        __(vpop1(arg_x))
1304        __(_rplacd(imm0,arg_z))
1305        __(_rplaca(imm0,arg_x))
1306        __(mov arg_z,imm0)
1307        __(add imm0,imm0,#cons.size)
1308        __(bne 1b)
1309        __(vpush1(arg_z))
1310        __(bx lr)
13112:
1312        __(movc16(imm0,make_header(1,subtag_u32_vector)))
1313        __(mov imm1,#0)
1314        __(stmdb sp!,{imm0,imm1})
1315        __(vpush1(arg_z))
1316        __(bx lr)
13173:
1318        __(mov arg_z,#stack_alloc_marker)
1319        __(mov arg_y,sp)
1320        __(stmdb sp!,{arg_z,arg_y})
1321        __(b _SPheap_cons_rest_arg)
1322
1323       
1324/* Prepend all but the first three (entrypoint, closure code, fn) and last two  */
1325/* (function name, lfbits) elements of nfn to the "arglist".  */
1326/* functions which take "inherited arguments" work consistently  */
1327/* even in cases where no closure object is created.  */
1328_spentry(call_closure)       
1329        __(cmp nargs,nargregs<<fixnumshift)
1330        __(vector_length(imm0,nfn,imm0))
1331        __(sub imm0,imm0,#5<<fixnumshift) /* imm0 = inherited arg count  */
1332        __(ble local_label(no_insert))
1333        /* Some arguments have already been vpushed.  Vpush imm0's worth  */
1334        /* of NILs, copy those arguments that have already been vpushed from  */
1335        /* the old TOS to the new, then insert all of the inerited args  */
1336        /* and go to the function.  */
1337        __(vpush_all_argregs())
1338        __(mov arg_x,imm0)
1339        __(mov arg_y,#nil_value)
1340local_label(push_nil_loop):
1341        __(subs arg_x,arg_x,#fixnumone)
1342        __(vpush1(arg_y))
1343        __(bne local_label(push_nil_loop))
1344        __(add arg_y,vsp,imm0)
1345        __(mov imm1,#0)
1346local_label(copy_already_loop):
1347        __(ldr arg_x,[arg_y,imm1])
1348        __(str arg_x,[vsp,imm1])
1349        __(add imm1,imm1,#fixnumone)
1350        __(cmp imm1,nargs)
1351        __(bne local_label(copy_already_loop))
1352        __(mov imm1,#misc_data_offset+(3<<fixnumshift))
1353        __(add arg_y,vsp,nargs)
1354        __(add arg_y,arg_y,imm0)
1355local_label(insert_loop):
1356        __(subs imm0,imm0,#fixnumone)
1357        __(ldr fname,[nfn,imm1])
1358        __(add imm1,imm1,#fixnumone)
1359        __(add nargs,nargs,#fixnumone)
1360        __(push1(fname,arg_y))
1361        __(bne local_label(insert_loop))
1362        __(vpop_all_argregs())
1363        __(b local_label(go))
1364local_label(no_insert):
1365/* nargregs or fewer args were already vpushed.  */
1366/* if exactly nargregs, vpush remaining inherited vars.  */
1367        __(cmp nargs,#nargregs<<fixnumshift)
1368        __(add imm1,imm0,#misc_data_offset+(3<<fixnumshift))
1369        __(bne local_label(set_regs))
1370local_label(vpush_remaining):
1371        __(mov imm1,#misc_data_offset+(3<<fixnumshift))
1372local_label(vpush_remaining_loop):             
1373        __(ldr fname,[nfn,imm1])
1374        __(add imm1,imm1,#fixnum_one)
1375        __(vpush1(fname))
1376        __(subs imm0,imm0,#fixnum_one)
1377        __(add nargs,nargs,#fixnum_one)
1378        __(bne  local_label(vpush_remaining_loop))
1379        __(b local_label(go))
1380local_label(set_regs):
1381        /* if nargs was > 1 (and we know that it was < 3), it must have  */
1382        /* been 2.  Set arg_x, then vpush the remaining args.  */
1383        __(cmp nargs,#fixnumone)
1384        __(ble local_label(set_y_z))
1385local_label(set_arg_x):
1386        __(subs imm0,imm0,#fixnum_one)
1387        __(sub imm1,imm1,#fixnum_one)
1388        __(ldr arg_x,[nfn,imm1])
1389        __(add nargs,nargs,#fixnum_one)
1390        __(bne local_label(vpush_remaining))
1391        __(b local_label(go))
1392        /* Maybe set arg_y or arg_z, preceding args  */
1393local_label(set_y_z):
1394        __(cmp nargs,#fixnumone)
1395        __(bne local_label(set_arg_z))
1396        /* Set arg_y, maybe arg_x, preceding args  */
1397local_label(set_arg_y):
1398        __(subs imm0,imm0,fixnum_one)
1399        __(sub imm1,imm1,#fixnum_one)
1400        __(ldr arg_y,[nfn,imm1])
1401        __(add nargs,nargs,#fixnum_one)
1402        __(bne local_label(set_arg_x))
1403        __(b local_label(go))
1404local_label(set_arg_z):
1405        __(subs imm0,imm0,#fixnum_one)
1406        __(sub imm1,imm1,#fixnum_one)
1407        __(ldr arg_z,[nfn,imm1])
1408        __(add nargs,nargs,#fixnum_one)
1409        __(bne local_label(set_arg_y))
1410 
1411local_label(go):
1412        __(vrefr(nfn,nfn,2))
1413        __(ldr pc,[nfn,#_function.entrypoint])
1414
1415
1416/* Everything up to the last arg has been vpushed, nargs is set to  */
1417/* the (boxed) count of things already pushed.  */
1418/* On exit, arg_x, arg_y, arg_z, and nargs are set as per a normal  */
1419/* function call (this may require vpopping a few things.)  */
1420/* ppc2-invoke-fn assumes that temp1 is preserved here.  */
1421_spentry(spreadargz)
1422        __(extract_lisptag(imm1,arg_z))
1423        __(cmp arg_z,#nil_value)
1424        __(mov imm0,#0)
1425        __(mov arg_y,arg_z)  /*  save in case of error  */
1426        __(beq 2f)
14271:
1428        __(cmp imm1,#tag_list)
1429        __(bne 3f)
1430        __(_car(arg_x,arg_z))
1431        __(_cdr(arg_z,arg_z))
1432        __(cmp arg_z,#nil_value)
1433        __(extract_lisptag(imm1,arg_z))
1434        __(vpush1(arg_x))
1435        __(add imm0,imm0,#fixnum_one)
1436        __(bne 1b)
14372:
1438        __(adds  nargs,nargs,imm0)
1439        __(bxeq lr)
1440        __(vpop_argregs_nz)
1441        __(bx lr)
1442       
1443        /*  Discard whatever's been vpushed already, complain.  */
14443: 
1445        __(add vsp,vsp,imm0)
1446        __(mov arg_z,arg_y)  /* recover original arg_z  */
1447        __(mov arg_y,#XNOSPREAD)
1448        __(set_nargs(2))
1449        __(b _SPksignalerr)
1450
1451/* Tail-recursively funcall temp0.  */
1452/* Pretty much the same as the tcallsym* cases above.  */
1453_spentry(tfuncallgen)
1454        __(cmp nargs,#nargregs<<fixnumshift)
1455        __(ldr lr,[sp,#lisp_frame.savelr])
1456        __(ldr fn,[sp,#lisp_frame.savefn])
1457        __(ble 2f)
1458        __(ldr imm0,[sp,#lisp_frame.savevsp])
1459        __(discard_lisp_frame())
1460        /* can use temp0 as a temporary  */
1461        __(sub imm1,nargs,#nargregs<<fixnumshift)
1462        __(add imm1,imm1,vsp)
14631:
1464        __(ldr temp0,[imm1,#-node_size]!)
1465        __(cmp imm1,vsp)
1466        __(push1(temp0,imm0))
1467        __(bne 1b)
1468        __(mov vsp,imm0)
1469        __(funcall_nfn())
14702:
1471        __(ldr vsp,[sp,#lisp_frame.savevsp])
1472        __(discard_lisp_frame())
1473        __(funcall_nfn())
1474
1475
1476/* Some args were vpushed.  Slide them down to the base of  */
1477/* the current frame, then do funcall.  */
1478_spentry(tfuncallslide)
1479        __(ldr fn,[sp,#lisp_frame.savefn])
1480        __(ldr imm0,[sp,#lisp_frame.savevsp])
1481        __(ldr lr,[sp,#lisp_frame.savelr])
1482        __(discard_lisp_frame())
1483        /* can use temp0 as a temporary  */
1484        __(sub imm1,nargs,#nargregs<<fixnumshift)
1485        __(add imm1,imm1,vsp)
14861:
1487        __(ldr temp0,[imm1,#-node_size]!)
1488        __(cmp imm1,vsp)
1489        __(push1(temp0,imm0))
1490        __(bne 1b)
1491        __(mov vsp,imm0)
1492        __(funcall_nfn())
1493
1494
1495_spentry(jmpsym)
1496        __(jump_fname)
1497
1498/* Tail-recursively call the (known symbol) in fname.  */
1499/* In the general case, we don't know if any args were  */
1500/* vpushed or not.  If so, we have to "slide" them down  */
1501/* to the base of the frame.  If not, we can just restore  */
1502/* vsp, lr, fn from the saved lisp frame on the control stack.  */
1503_spentry(tcallsymgen)
1504        __(cmp nargs,#nargregs<<fixnumshift)
1505        __(ldr lr,[sp,#lisp_frame.savelr])
1506        __(ldr fn,[sp,#lisp_frame.savefn])
1507        __(ble 2f)
1508
1509        __(ldr imm0,[sp,#lisp_frame.savevsp])
1510        __(discard_lisp_frame())
1511        /* can use nfn (= temp2) as a temporary  */
1512        __(sub imm1,nargs,#nargregs<<fixnumshift)
1513        __(add imm1,imm1,vsp)
15141:
1515        __(ldr temp2,[imm1,#-node_size]!)
1516        __(cmp imm1,vsp)
1517        __(push1(temp2,imm0))
1518        __(bne 1b)
1519        __(mov vsp,imm0)
1520        __(jump_fname)
1521 
15222: 
1523        __(ldr vsp,[sp,#lisp_frame.savevsp])
1524        __(discard_lisp_frame())
1525        __(jump_fname)
1526
1527
1528/* Some args were vpushed.  Slide them down to the base of  */
1529/* the current frame, then do funcall.  */
1530_spentry(tcallsymslide)
1531        __(ldr lr,[sp,#lisp_frame.savelr])
1532        __(ldr fn,[sp,#lisp_frame.savefn])
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
1546
1547/* Tail-recursively call the function in nfn.  */
1548/* Pretty much the same as the tcallsym* cases above.  */
1549_spentry(tcallnfngen)
1550        __(cmp nargs,#nargregs<<fixnumshift)
1551        __(bgt _SPtcallnfnslide)
1552        __(restore_lisp_frame(imm0))
1553        __(jump_nfn())
1554         
1555/* Some args were vpushed.  Slide them down to the base of  */
1556/* the current frame, then do funcall.  */
1557_spentry(tcallnfnslide)
1558        __(ldr lr,[sp,#lisp_frame.savelr])
1559        __(ldr fn,[sp,#lisp_frame.savefn])
1560        __(ldr imm0,[sp,#lisp_frame.savevsp])
1561        __(discard_lisp_frame())
1562        /* Since we have a known function, can use fname as a temporary.  */
1563        __(sub imm1,nargs,#nargregs<<fixnumshift)
1564        __(add imm1,imm1,vsp)
15651:
1566        __(ldr fname,[imm1,#-node_size]!)
1567        __(cmp imm1,vsp)
1568        __(push1(fname,imm0))
1569        __(bne 1b)
1570        __(mov vsp,imm0)
1571        __(jump_nfn())
1572
1573
1574/* Reference index arg_z of a misc-tagged object (arg_y).  */
1575/* Note that this conses in some cases.  Return a properly-tagged  */
1576/* lisp object in arg_z.  Do type and bounds-checking.  */
1577
1578_spentry(misc_ref)
1579        __(trap_unless_fulltag_equal(arg_y,fulltag_misc,imm0))
1580        __(trap_unless_fixnum(arg_z))
1581        __(vector_length(imm0,arg_y,imm1))
1582        __(cmp arg_z,imm0)
1583        __(uuo_error_vector_bounds(hs,arg_z,arg_y))
1584        __(extract_lowbyte(imm1,imm1)) /* imm1 = subtag  */
1585        __(b C(misc_ref_common))
1586
1587/* like misc_ref, only the boxed subtag is in arg_x.  */
1588
1589_spentry(subtag_misc_ref)
1590        __(trap_unless_fulltag_equal(arg_y,fulltag_misc,imm0))
1591        __(trap_unless_fixnum(arg_z))
1592        __(vector_length(imm0,arg_y,imm1))
1593        __(cmp arg_z,imm0)
1594        __(uuo_error_vector_bounds(hs,arg_z,arg_y))
1595        __(unbox_fixnum(imm1,arg_x))
1596        __(b C(misc_ref_common))
1597
1598
1599/* Make a "raw" area on the temp stack, stack-cons a macptr to point to it,  */
1600/* and return the macptr.  Size (in bytes, boxed) is in arg_z on entry; macptr */
1601/* in arg_z on exit.  */
1602_spentry(makestackblock)
1603        __(unbox_fixnum(imm1,arg_z))
1604        __(dnode_align(imm1,imm1,0))
1605        __(add imm1,imm1,#node_size)
1606        __(add imm0,imm1,#node_size)
1607        __(cmp imm0,#stack_alloc_limit)
1608        __(mov temp0,sp)
1609        __(bhs 1f)
1610        __(mov imm1,imm1,lsl #num_subtag_bits)
1611        __(orr imm1,imm1,#subtag_u8_vector)
1612        __(stack_allocate_ivector(imm1,imm0))
1613        __(add temp1,sp,#dnode_size)
1614        __(movc16(imm1,make_header(macptr.element_count,subtag_macptr)))
1615        __(str imm1,[sp,#-macptr.size]!)
1616        __(add arg_z,sp,#fulltag_misc)
1617        __(str temp1,[arg_z,#macptr.address])
1618        __(mov imm0,#0)
1619        __(mov imm1,#stack_alloc_marker)
1620        __(str imm0,[arg_z,#macptr.type])
1621        __(str imm0,[arg_z,#macptr.domain])
1622        __(stmdb sp!,{imm1,temp0})
1623        __(bx lr)
1624
1625        /* Too big. Heap cons a gcable macptr  */
16261:
1627        __(mov imm1,#stack_alloc_marker)
1628        __(stmdb sp!,{imm1,temp0})
1629        __(set_nargs(1))
1630        __(ref_nrs_symbol(fname,new_gcable_ptr,imm0))
1631        __(jump_fname())
1632
1633/* As above, only set the block's contents to 0.  */
1634_spentry(makestackblock0)
1635        __(unbox_fixnum(imm1,arg_z))
1636        __(dnode_align(imm1,imm1,0))
1637        __(add imm1,imm1,#node_size)
1638        __(add imm0,imm1,#node_size)
1639        __(cmp imm0,#stack_alloc_limit)
1640        __(mov temp0,sp)
1641        __(bhs 1f)
1642        __(mov imm1,imm1,lsl #num_subtag_bits)
1643        __(orr imm1,imm1,#subtag_u8_vector)
1644        __(stack_allocate_zeroed_ivector(imm1,imm0))
1645        __(add temp1,sp,#dnode_size)
1646        __(movc16(imm1,make_header(macptr.element_count,subtag_macptr)))
1647        __(str imm1,[sp,#-macptr.size]!)
1648        __(add arg_z,sp,#fulltag_misc)
1649        __(str temp1,[arg_z,#macptr.address])
1650        __(mov imm0,#0)
1651        __(mov imm1,#stack_alloc_marker)
1652        __(str imm0,[arg_z,#macptr.type])
1653        __(str imm0,[arg_z,#macptr.domain])
1654        __(stmdb sp!,{imm1,temp0})
1655        __(bx lr)
1656       
1657        /* Too big. Heap cons a gcable macptr  */
16581:
1659        __(mov imm1,#stack_alloc_marker)
1660        __(stmdb sp!,{imm1,temp0})
1661        __(mov arg_y,arg_z) /* save block size  */
1662        __(mov arg_z,#nil_value) /* clear-p arg to %new-gcable-ptr  */
1663        __(add arg_z,arg_z,#t_offset)
1664        __(set_nargs(2))
1665        __(ref_nrs_symbol(fname,new_gcable_ptr,imm0))
1666        __(jump_fname())
1667
1668/* Make a list of length arg_y (boxed), initial-element arg_z (boxed) on  */
1669/* the tstack.  Return the list in arg_z.  */
1670_spentry(makestacklist)
1671        __(add imm0,arg_y,arg_y)
1672        __(mov imm1,imm0,lsl #num_subtag_bits-fixnumshift)
1673        __(add imm1,imm1,#1<<num_subtag_bits)
1674        __(orr imm1,imm1,#subtag_u32_vector)
1675        __(add imm0,imm0,#dnode_size)
1676        __(cmp imm0,#stack_alloc_limit)
1677        __(bge 4f)
1678        __(stack_allocate_zeroed_ivector(imm1,imm0))
1679        __(mov imm0,#subtag_simple_vector)
1680        __(strb imm0,[sp,#0])
1681        __(add imm2,sp,#dnode_size+fulltag_cons)
1682        __(movs imm1,arg_y)
1683        __(mov arg_y,arg_z)
1684        __(mov arg_z,#nil_value)
1685        __(b 3f)
16862:
1687        __(_rplacd(imm2,arg_z))
1688        __(_rplaca(imm2,arg_y))
1689        __(mov arg_z,imm2)
1690        __(add imm2,imm2,#cons.size)
1691        __(subs imm1,imm1,#fixnumone)
16923:
1693        __(bne 2b)
1694        __(bx lr)
16954:
1696        __(movc16(imm0,make_header(1,subtag_u32_vector)))
1697        __(str imm0,[sp,#-8]!)
1698        __(movs imm1,arg_y) /* count  */
1699        __(mov arg_y,arg_z) /* initial value  */
1700        __(mov arg_z,#nil_value) /* result  */
1701        __(b 6f)
17025:
1703        __(Cons(arg_z,arg_y,arg_z))
1704        __(subs imm1,imm1,#fixnumone)
17056:
1706        __(bne 5b)
1707        __(bx lr)
1708
1709/* subtype (boxed) vpushed before initial values. (Had better be a  */
1710/* node header subtag.) Nargs set to count of things vpushed.  */
1711
1712_spentry(stkgvector)
1713        __(sub imm0,nargs,#fixnumone)
1714        __(ldr temp0,[vsp,imm0])
1715        __(dnode_align(temp1,imm0,node_size))
1716        __(mov imm1,imm0,lsl #num_subtag_bits-fixnumshift)
1717        __(orr imm1,imm1,#subtag_u32_vector)
1718        __(mov temp2,sp)
1719        __(mov arg_x,#stack_alloc_marker)
1720        __(stack_allocate_zeroed_ivector(imm1,temp1))
1721        __(unbox_fixnum(imm1,temp0))
1722        __(strb imm1,[sp])
1723        __(add arg_z,sp,#fulltag_misc)
1724        __(add imm0,sp,nargs)
1725        __(stmdb sp!,{arg_x,temp2})
1726        __(b 2f)
17271:
1728        __(vpop1(temp0))
1729        __(push1(temp0,imm0))
17302:      __(subs nargs,nargs,#fixnumone)
1731        __(bne 1b)
1732        __(add vsp,vsp,#fixnumone)
1733        __(bx lr)
1734
1735/* Allocate a "fulltag_misc" object.  On entry, arg_y contains the element  */
1736/* count (boxed) and  arg_z contains the subtag (boxed).  Both of these   */
1737/* parameters must be "reasonable" (the  subtag must be valid, the element  */
1738/* count must be of type (unsigned-byte 24)/(unsigned-byte 56).   */
1739/* On exit, arg_z contains the (properly tagged) misc object; it'll have a  */
1740/* proper header on it and its contents will be 0.   imm0 contains   */
1741/* the object's header (fulltag = fulltag_immheader or fulltag_nodeheader.)  */
1742
1743_spentry(misc_alloc)
1744        __(tst arg_y,#unsigned_byte_24_mask)
1745        __(bne 9f)
1746        __(unbox_fixnum(imm0,arg_z))
1747        __(orr imm0,imm0,arg_y,lsl #num_subtag_bits-fixnumshift)
1748        __(extract_fulltag(imm1,imm0))
1749        __(cmp imm1,#fulltag_nodeheader)
1750        __(mov imm2,arg_y)      /* imm2 = logical size in bytes */
1751        __(beq 1f)
1752        __(unbox_fixnum(imm1,arg_z))
1753        __(cmp imm1,#max_32_bit_ivector_subtag)
1754        __(ble 1f)
1755        __(mov imm2,arg_y,lsr #2)
1756        __(cmp imm1,#max_8_bit_ivector_subtag)
1757        __(ble 1f)
1758        __(mov imm2,arg_y,lsr #1)
1759        __(cmp imm1,#max_16_bit_ivector_subtag)
1760        __(ble 1f)
1761        __(mov imm2,arg_y,lsl #1)
1762        __(add imm2,imm2,#node_size)
1763        __(cmp imm1,#subtag_double_float_vector)
1764        __(beq 1f)
1765        __(add imm2,arg_y,#7<<fixnumshift)
1766        __(mov imm2,imm2,lsr #3+fixnumshift)
1767        /* imm2 now = byte count.  Add 4 for header, 7 to align, then clear */
1768        /* low three bits.  */
17691:
1770        __(dnode_align(imm2,imm2,node_size))
1771        __(Misc_Alloc(arg_z,imm0,imm2))
1772        __(bx lr)
17739:
1774        __(uuo_error_reg_not_xtype(al,arg_y,xtype_unsigned_byte_24))
1775
1776
1777
1778/* This doesn't need to memoize anything, but needs pc-lusering support
1779   support because of the locative */
1780_spentry(atomic_incf_node)
1781        __(unbox_fixnum(imm1,arg_z))
17820:      __(add imm2,arg_y,imm1)
1783        __(ldrex arg_z,[imm2])
1784        __(add arg_z,arg_z,arg_x)
1785        __(strex imm0,arg_z,[imm2])
1786        __(cmp imm0,#0)
1787        __(bne 0b)
1788        __(bx lr)
1789       
1790_spentry(unused1)
1791
1792_spentry(unused2)
1793
1794/* vpush the values in the value set atop the stack, incrementing nargs.  */
1795
1796define(`mvcall_older_value_set',`node_size')
1797define(`mvcall_younger_value_set',`node_size+4')
1798       
1799
1800_spentry(recover_values)
1801        __(add temp0,sp,#dnode_size)
1802        /* Find the oldest set of values by walking links from the newest */
18030:             
1804        __(ldr temp1,[temp0,#mvcall_older_value_set])
1805        __(cmp temp1,#0)
1806        __(movne temp0,temp1)
1807        __(bne 0b)
18081:      __(ldr imm0,[temp0])
1809        __(header_length(imm0,imm0))
1810        __(subs imm0,imm0,#2<<fixnumshift)
1811        __(add temp1,temp0,#node_size+8)
1812        __(add temp1,temp1,imm0)
1813        __(b 3f)
18142:      __(subs imm0,imm0,#fixnumone)       
1815        __(ldr arg_z,[temp1,#-node_size]!)
1816        __(vpush1(arg_z))
1817        __(add nargs,nargs,#fixnumone)
18183:      __(bne 2b)
1819        __(ldr temp0,[temp0,#mvcall_younger_value_set])
1820        __(cmp temp0,#0)
1821        __(bne 1b)
1822        __(ldr sp,[sp,#node_size])
1823        __(bx lr)
1824
1825
1826/* If arg_z is an integer, return in imm0 something whose sign  */
1827/* is the same as arg_z's.  If not an integer, error.  */
1828_spentry(integer_sign)
1829        __(test_fixnum(arg_z))
1830        __(moveq imm0,arg_z)
1831        __(bxeq lr)
1832        __(extract_typecode(imm0,arg_z))
1833        __(cmp imm0,#subtag_bignum)
1834        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_integer))
1835        __(getvheader(imm1,arg_z))
1836        __(header_length(imm0,imm1)) /* boxed length = scaled size  */
1837        __(add imm0,imm0,#misc_data_offset-4) /* bias, less 1 element  */
1838        __(ldr imm0,[arg_z,imm0])
1839        __(cmp imm0,#0)
1840        __(movge imm0,#1)
1841        __(movlt imm0,#-1)
1842        __(bx lr)
1843
1844
1845/* like misc_set, only pass the (boxed) subtag in temp0  */
1846_spentry(subtag_misc_set)
1847        __(trap_unless_fulltag_equal(arg_x,fulltag_misc,imm0))
1848        __(trap_unless_fixnum(arg_y))
1849        __(vector_length(imm0,arg_x,imm1))
1850        __(cmp arg_y,imm0)
1851        __(uuo_error_vector_bounds(hs,arg_y,arg_x))
1852        __(unbox_fixnum(imm1,temp0))
1853        __(b C(misc_set_common))
1854
1855
1856
1857/* misc_set (vector index newval).  Pretty damned similar to  */
1858/* misc_ref, as one might imagine.  */
1859
1860_spentry(misc_set)
1861        __(trap_unless_fulltag_equal(arg_x,fulltag_misc,imm0))
1862        __(trap_unless_fixnum(arg_y))
1863        __(vector_length(imm0,arg_x,imm1))
1864        __(cmp arg_y,imm0)
1865        __(uuo_error_vector_bounds(hs,arg_y,arg_x))
1866        __(extract_lowbyte(imm1,imm1))
1867        __(b C(misc_set_common))
1868
1869/* "spread" the lexpr in arg_z.  */
1870/* ppc2-invoke-fn assumes that temp1 is preserved here.  */
1871_spentry(spread_lexprz)
1872        __(ldr imm0,[arg_z,#0])
1873        __(add imm1,arg_z,imm0)
1874        __(add nargs,nargs,imm0)
1875        __(add imm1,imm1,#node_size)
1876        __(cmp imm0,#3<<fixnumshift)
1877        __(bge 9f)
1878        __(cmp imm0,#2<<fixnumshift)
1879        __(beq 2f)
1880        __(cmp imm0,#0)
1881        __(bne 1f)
1882/* lexpr count was 0; vpop the arg regs that  */
1883/* were vpushed by the caller  */
1884        __(cmp nargs,#0)
1885        __(bxeq lr)
1886        __(vpop_argregs_nz)
1887        __(bx lr)
1888
1889/* vpush args from the lexpr until we have only  */
1890/* three left, then assign them to arg_x, arg_y,  */
1891/* and arg_z.  */
18928:
1893        __(cmp imm0,#4<<fixnumshift)
1894        __(sub imm0,imm0,#fixnumone)
1895        __(ldr arg_z,[imm1,#-node_size]!)
1896        __(vpush1(arg_z))
18979:
1898        __(bne 8b)
1899        __(ldr arg_x,[imm1,#-node_size*1])
1900        __(ldr arg_y,[imm1,#-node_size*2])
1901        __(ldr arg_z,[imm1,#-node_size*3])
1902        __(bx lr)
1903
1904/* lexpr count is two: set arg_y, arg_z from the  */
1905/* lexpr, maybe vpop arg_x  */
19062:
1907        __(cmp nargs,#2<<fixnumshift)
1908        __(ldr arg_y,[imm1,#-node_size*1])
1909        __(ldr arg_z,[imm1,#-node_size*2])
1910        __(bxeq lr)  /* return if (new) nargs = 2  */
1911        __(vpop1(arg_x))
1912        __(bx lr)
1913
1914/* lexpr count is one: set arg_z from the lexpr,  */
1915/* maybe vpop arg_y, arg_x  */
19161: 
1917        __(cmp nargs,#2<<fixnumshift)
1918        __(ldr arg_z,[imm1,#-node_size])
1919        __(bxlt lr)  /* return if (new) nargs < 2  */
1920        __(vpop1(arg_y))
1921        __(bxeq lr)  /* return if (new) nargs = 2  */
1922        __(vpop1(arg_x))
1923        __(bx lr)
1924
1925
1926_spentry(reset)
1927        __(nop)
1928        __(ref_nrs_value(temp0,toplcatch))
1929        __(mov temp1,#XSTKOVER)
1930        __(vpush1(temp0))
1931        __(vpush1(temp1))
1932        __(set_nargs(1))
1933        __(b _SPthrow)
1934
1935
1936/* "slide" nargs worth of values up the vstack.  IMM0 contains  */
1937/* the difference between the current VSP and the target.  */
1938_spentry(mvslide)
1939        __(cmp nargs,#0)
1940        __(mov temp1,nargs)
1941        __(add imm1,vsp,nargs)
1942        __(add imm1,imm1,imm0)
1943        __(add imm0,vsp,nargs)
1944        __(beq 2f)
19451:
1946        __(subs temp1,temp1,#1<<fixnumshift)
1947        __(ldr temp0,[imm0,#-node_size]!)
1948        __(str temp0,[imm1,#-node_size]!)
1949        __(bne 1b)
19502:
1951        __(mov vsp,imm1)
1952        __(bx lr)
1953
1954                     
1955_spentry(save_values)
1956        __(mov temp1,#0)
1957        __(mov arg_x,sp)
1958local_label(save_values_to_tsp):
1959        __(add imm1,nargs,#node_size*2)
1960        __(dnode_align(imm0,imm1,node_size))
1961        __(mov imm1,imm1,lsl #num_subtag_bits-fixnumshift)
1962        __(orr imm1,imm1,#subtag_u32_vector)
1963        __(stack_allocate_zeroed_ivector(imm1,imm0))
1964        __(cmp temp1,$0)
1965        __(mov imm1,#subtag_simple_vector)
1966        __(mov arg_y,#stack_alloc_marker)
1967        __(strb imm1,[sp])
1968        __(mov temp0,sp)
1969        __(stmdb sp!,{arg_y,arg_x})
1970        __(str temp1,[temp0,#mvcall_older_value_set])
1971        __(strne temp0,[temp1,#mvcall_younger_value_set])
1972        __(add temp0,temp0,#node_size+8)
1973        __(mov imm0,#0)
1974        __(b 2f)
19751:      __(vpop1(temp1))
1976        __(str temp1,[temp0],#node_size)
1977        __(add imm0,imm0,#node_size)
19782:      __(cmp imm0,nargs)
1979        __(bne 1b)
1980        __(bx lr)
1981       
1982_spentry(add_values)
1983        __(cmp nargs,#0)
1984        __(ldr arg_x,[sp,#node_size])
1985        __(bxeq lr)
1986        __(add sp,sp,#dnode_size)
1987        __(mov temp1,sp)
1988        __(b local_label(save_values_to_tsp))
1989
1990
1991/* Like misc_alloc (a LOT like it, since it does most of the work), but takes  */
1992/* an initial-value arg in arg_z, element_count in arg_x, subtag in arg_y.  */
1993/* Calls out to %init-misc, which does the rest of the work.  */
1994
1995_spentry(misc_alloc_init)
1996        __(build_lisp_frame(imm0))
1997        __(mov fn,#0)
1998        __(mov temp2,arg_z)  /* initval  */
1999        __(mov arg_z,arg_y)  /* subtag  */
2000        __(mov arg_y,arg_x)  /* element-count  */
2001        __(bl _SPmisc_alloc)
2002        __(restore_lisp_frame(imm0))
2003        __(mov arg_y,temp2)
2004initialize_vector:             
2005        __(ref_nrs_symbol(fname,init_misc,imm0))
2006        __(set_nargs(2))
2007        __(jump_fname())
2008
2009/* As in stack_misc_alloc above, only with a non-default initial-value.  */
2010/* Note that this effectively inlines _SPstack_misc_alloc. */               
2011 
2012_spentry(stack_misc_alloc_init)
2013        __(tst arg_x,#unsigned_byte_24_mask)
2014        __(uuo_error_reg_not_xtype(ne,arg_x,xtype_unsigned_byte_24))
2015        __(unbox_fixnum(imm0,arg_y))
2016        __(extract_fulltag(imm1,imm0))
2017        __(cmp imm1,#fulltag_nodeheader)
2018        __(bne 1f)
2019        __(dnode_align(imm1,arg_x,node_size))
2020        __(cmp imm1,#stack_alloc_limit)
2021        __(bge 0f)
2022        __(mov imm0,#subtag_u32_vector)
2023        __(orr imm0,imm0,arg_x,lsl #num_subtag_bits-fixnumshift)
2024        __(mov temp0,#stack_alloc_marker)
2025        __(mov temp1,sp)
2026        __(stack_allocate_zeroed_ivector(imm0,imm1))
2027        __(unbox_fixnum(imm0,arg_y))
2028        __(strb imm0,[sp])
2029        __(mov arg_y,arg_z)
2030        __(add arg_z,sp,#fulltag_misc)
2031        __(stmdb sp!,{temp0,temp1})
2032        __(b initialize_vector)
20331:      __(mov imm0,arg_x,lsl #num_subtag_bits-fixnumshift)
2034        __(orr imm0,imm0,arg_y,lsr #fixnumshift)
2035        __(cmp arg_y,#max_32_bit_ivector_subtag<<fixnumshift)
2036        __(movle imm1,arg_x)
2037        __(ble 8f)
2038        __(cmp arg_y,#max_8_bit_ivector_subtag<<fixnumshift)
2039        __(movle imm1,arg_x,lsr #fixnumshift)
2040        __(ble 8f)
2041        __(cmp arg_y,#max_16_bit_ivector_subtag<<fixnumshift)
2042        __(movle imm1,arg_x,lsr #1)
2043        __(ble 8f)
2044        __(cmp arg_y,#subtag_double_float)
2045        __(moveq imm1,arg_x,lsl #1)
2046        __(addeq imm1,imm1,#node_size)
2047        __(addne imm1,arg_x,#7<<fixnumshift)
2048        __(movne imm1,imm1,lsr#3+fixnumshift)
20498:      __(dnode_align(imm1,imm1,node_size))
2050        __(cmp imm1,#stack_alloc_limit)
2051        __(bhs 0f)
2052        __(mov temp0,#stack_alloc_marker)
2053        __(mov temp1,sp)
2054        __(stack_allocate_zeroed_ivector(imm0,imm1))
2055        __(mov arg_y,arg_z)
2056        __(add arg_z,sp,#fulltag_misc)
2057        __(stmdb sp!,{temp0,temp1})
2058        __(b initialize_vector)
2059
2060 
2061_spentry(popj)
2062        .globl C(popj)
2063C(popj):
2064        __(return_lisp_frame(imm0))
2065       
2066/* Too large to safely fit on tstack.  Heap-cons the vector, but make  */
2067/* sure that there's an empty tsp frame to keep the compiler happy.  */
20680:
2069        __(mov imm0,#stack_alloc_marker)
2070        __(mov imm1,sp)
2071        __(stmdb sp!,{imm0,imm1})
2072        __(b _SPmisc_alloc_init)
2073
2074
2075/* Divide the 64 bit unsigned integer in imm0 (low) and imm1 (high) by
2076   the 32-bit unsigned integer in imm2; return the quotient in
2077   imm0:imm1 and remainder in imm2.  We pretty much have to do this
2078   as an ff call; even if we wrote the code ourselves, we'd have to
2079   enter foreign context to use as many imm regs as we'd need.
2080   Moral: don't do integer division on the ARM.
2081*/
2082        .globl C(__aeabi_uldivmod)       
2083_spentry(udiv64by32)
2084        __(cmp imm2,#0)
2085        __(moveq arg_z,#XDIVZRO)
2086        __(moveq nargs,#1<<fixnumshift)
2087        __(beq _SPksignalerr)
2088        __(stmdb vsp!,{arg_z,arg_y,arg_x,temp0,temp1,temp2})
2089        __(str vsp,[rcontext,#tcr.save_vsp])
2090        __(mov arg_z,rcontext)
2091        __(ldr arg_y,[rcontext,#tcr.last_lisp_frame])
2092        __(build_lisp_frame(r3))
2093        __(str sp,[arg_z,#tcr.last_lisp_frame])
2094        __(str allocptr,[arg_z,#tcr.save_allocptr])
2095        __(mov r3,#TCR_STATE_FOREIGN)
2096        __(str r3,[arg_z,#tcr.valence])
2097        __(mov r3,#0)
2098        __(bl C(__aeabi_uldivmod))
2099        __(mov rcontext,arg_z)
2100        __(str arg_y,[rcontext,#tcr.last_lisp_frame])
2101        __(mov allocptr,#VOID_ALLOCPTR)
2102        __(mov fn,#0)
2103        __(mov temp2,#0)
2104        __(mov temp1,#0)
2105        __(mov temp0,#0)
2106        __(mov arg_x,#TCR_STATE_LISP)
2107        __(str arg_x,[rcontext,#tcr.valence])
2108        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
2109        __(ldm vsp!,{arg_z,arg_y,arg_x,temp0,temp1,temp2})
2110        __(ldr fn,[sp,#lisp_frame.savefn])
2111        __(ldr lr,[sp,#lisp_frame.savelr])
2112        __(discard_lisp_frame())
2113        __(bx lr)
2114
2115
2116/* arg_z should be of type (UNSIGNED-BYTE 64);  */
2117/* return high 32 bits in imm1, low 32 bits in imm0 */
2118
2119
2120_spentry(getu64)
2121        __(test_fixnum(arg_z))
2122        __(bne 1f)
2123        __(unbox_fixnum(imm0,arg_z))
2124        __(movs imm1,imm0,asr #31)
2125        __(bxeq lr)
21260:             
2127        __(uuo_error_reg_not_xtype(al,arg_z,xtype_u64))
21281:
2129        __(extract_typecode(imm0,arg_z))
2130        __(cmp imm0,#subtag_bignum)
2131        __(bne 0b)
2132        __(movc16(imm1,two_digit_bignum_header))
2133        __(getvheader(imm0,arg_z))
2134        __(cmp imm0,imm1)
2135        __(bne 2f)
2136        __(vrefr(imm0,arg_z,0))
2137        __(vrefr(imm1,arg_z,1))
2138        __(cmp imm1,#0)
2139        __(bxge lr)
2140        __(uuo_error_reg_not_xtype(al,arg_z,xtype_u64))
21412:      __(movc16(imm1,three_digit_bignum_header))
2142        __(cmp imm0,imm1)
2143        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u64))
2144        __(vrefr(imm2,arg_z,2))
2145        __(cmp imm2,#0)
2146        __(vrefr(imm1,arg_z,1))
2147        __(vrefr(imm0,arg_z,0))
2148        __(bxeq lr)
2149        __(uuo_error_reg_not_xtype(al,arg_z,xtype_u64))
2150
2151         
2152/* arg_z should be of type (SIGNED-BYTE 64);  */
2153/*    return high 32 bits  in imm1, low 32 bits in imm0  */
2154
2155_spentry(gets64)
2156        __(test_fixnum(arg_z))
2157        __(moveq imm0,arg_z,asr #fixnumshift)
2158        __(moveq imm1,imm0,asr #31)
2159        __(bxeq lr)
2160        __(mov imm2,#0)
2161        __(extract_lisptag(imm0,arg_z))
2162        __(cmp imm0,#tag_misc)
2163        __(ldreq imm2,[arg_z,#misc_header_offset])
2164        __(movc16(imm1,two_digit_bignum_header))
2165        __(cmp imm1,imm2)
2166        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_s64))
2167        __(vrefr(imm1,arg_z,1))
2168        __(vrefr(imm0,arg_z,0))
2169        __(bx lr)
2170
2171
2172/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
2173/* unbound_marker), arg_y = symbol, imm1 = symbol.binding-index  */
2174_spentry(specref)
2175        __(ldr imm1,[arg_z,#symbol.binding_index])
2176        __(ldr imm0,[rcontext,#tcr.tlb_limit])
2177        __(cmp imm1,imm0)
2178        __(ldr temp0,[rcontext,#tcr.tlb_pointer])
2179        __(mov arg_y,arg_z)
2180        __(movhs imm1,#0)
2181        __(ldr arg_z,[temp0,imm1])
2182        __(cmp arg_z,#no_thread_local_binding_marker)
2183        __(ldreq arg_z,[arg_y,#symbol.vcell])
2184        __(bx lr)
2185
2186_spentry(specrefcheck)
2187        __(ldr imm1,[arg_z,#symbol.binding_index])
2188        __(ldr imm0,[rcontext,#tcr.tlb_limit])
2189        __(cmp imm1,imm0)
2190        __(movhs imm1,#0)
2191        __(ldr imm0,[rcontext,#tcr.tlb_pointer])
2192        __(mov arg_y,arg_z)
2193        __(ldr arg_z,[imm0,imm1])
2194        __(cmp arg_z,#no_thread_local_binding_marker)
2195        __(ldreq arg_z,[arg_y,#symbol.vcell])
2196        __(cmp arg_z,#unbound_marker)
2197        __(uuo_error_unbound(eq,arg_y))
2198        __(bx lr)
2199
2200/* arg_y = special symbol, arg_z = new value.          */
2201_spentry(specset)
2202        __(ldr imm1,[arg_y,#symbol.binding_index])
2203        __(ldr imm0,[rcontext,#tcr.tlb_limit])
2204        __(ldr imm2,[rcontext,#tcr.tlb_pointer])
2205        __(cmp imm1,imm0)
2206        __(movge imm1,#0)
2207        __(ldr temp1,[imm2,imm1])
2208        __(cmp temp1,#no_thread_local_binding_marker)
2209        __(strne arg_z,[imm2,imm1])
2210        __(bxne lr)
2211        __(mov arg_x,arg_y)
2212        __(mov arg_y,#symbol.vcell-misc_data_offset)
2213        __(b _SPgvset)
2214
2215
2216       
2217/* Construct a lisp integer out of the 32-bit signed value in imm0 */
2218/* arg_z should be of type (SIGNED-BYTE 32); return unboxed result in imm0 */
2219
2220_spentry(gets32)
2221        __(test_fixnum(arg_z))
2222        __(moveq imm0,arg_z,asr #fixnumshift)
2223        __(bxeq lr)
2224        __(extract_lisptag(imm0,arg_z))
2225        __(cmp imm0,#tag_misc)
2226        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_s32))
2227        __(getvheader(imm0,arg_z))
2228        __(movc16(imm1,one_digit_bignum_header))
2229        __(cmp imm0,imm1)
2230        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_s32))
2231        __(vrefr(imm0,arg_z,0))
2232        __(bx lr)       
2233
2234
2235/*  */
2236/* arg_z should be of type (UNSIGNED-BYTE 32); return unboxed result in imm0 */
2237/*  */
2238
2239_spentry(getu32)
2240        __(test_fixnum(arg_z))
2241        __(moveq imm0,arg_z,asr #fixnumshift)
2242        __(movseq imm1,imm0,asr #31)
2243        __(bxeq lr)
2244        __(movc16(imm1,one_digit_bignum_header))
2245        __(extract_lisptag(imm0,arg_z))
2246        __(cmp imm0,#tag_misc)
2247        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u32))
2248        __(getvheader(imm0,arg_z))
2249        __(cmp imm0,imm1)
2250        __(ldreq imm0,[arg_z,#misc_data_offset])
2251        __(beq 7f)
2252        __(movc16(imm1,two_digit_bignum_header))
2253        __(cmp imm0,imm1)
2254        __(ldreq imm0,[arg_z,#misc_data_offset])
2255        __(ldreq imm1,[arg_z,#misc_data_offset+4])
2256        __(cmpeq imm1,#0)
2257        __(bxeq lr)
2258        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u32))
22597:             
2260        __(movs imm1,imm0,asr #31)
2261        __(bxeq lr)
2262        __(uuo_error_reg_not_xtype(ne,arg_z,xtype_u32))
2263
2264
2265/* */
2266/* As per mvpass above, but in this case fname is known to be a */
2267/* symbol. */
2268
2269_spentry(mvpasssym)
2270        __(cmp nargs,#node_size*nargregs)
2271        __(mov imm1,vsp)
2272        __(subgt imm1,imm1,#node_size*nargregs)
2273        __(addgt imm1,imm1,nargs)
2274        __(build_lisp_frame(imm0,imm1))
2275        __(ref_global(lr,ret1val_addr,imm0))
2276        __(mov fn,#0)
2277        __(jump_fname())
2278
2279_spentry(unbind)
2280        __(ldr imm1,[rcontext,#tcr.db_link])
2281        __(ldr temp0,[rcontext,#tcr.tlb_pointer])   
2282        __(ldr imm0,[imm1,#binding.sym])
2283        __(ldr temp1,[imm1,#binding.val])
2284        __(ldr imm1,[imm1,#binding.link])
2285        __(str temp1,[temp0,imm0])
2286        __(str imm1,[rcontext,#tcr.db_link])
2287        __(bx lr)
2288
2289/* Clobbers imm1,temp0,arg_x, arg_y */       
2290_spentry(unbind_n)
2291        __(ldr imm1,[rcontext,#tcr.db_link])
2292        __(ldr arg_x,[rcontext,#tcr.tlb_pointer])
22931:      __(ldr temp0,[imm1,#binding.sym])
2294        __(ldr arg_y,[imm1,#binding.val])
2295        __(ldr imm1,[imm1,#binding.link])
2296        __(subs imm0,imm0,#1)
2297        __(str arg_y,[arg_x,temp0])
2298        __(bne 1b)
2299        __(str imm1,[rcontext,#tcr.db_link])
2300        __(bx lr)
2301
2302/* */
2303/* Clobbers imm1,temp0,arg_x, arg_y */
2304
2305_spentry(unbind_to)
2306        do_unbind_to(imm1,temp1,arg_x,arg_y)
2307        __(bx lr)
2308 
2309
2310 
2311/* */
2312/* Restore the special bindings from the top of the tstack,  */
2313/* leaving the tstack frame allocated.  */
2314/* Note that there might be 0 saved bindings, in which case  */
2315/* do nothing.  */
2316/* Note also that this is -only- called from an unwind-protect  */
2317/* cleanup form, and that .SPnthrowXXX is keeping one or more  */
2318/* values in a frame on top of the tstack.  */
2319/*  */
2320                         
2321_spentry(progvrestore)
2322        __(skip_stack_vector(imm0,imm1,sp))
2323        __(ldr imm0,[imm0,#lisp_frame.size+node_size])
2324        __(cmp imm0,#0)
2325        __(unbox_fixnum(imm0,imm0))
2326        __(bne _SPunbind_n)
2327        __(bx lr)
2328
2329/* Bind CCL::*INTERRUPT-LEVEL* to 0.  If its value had been negative, check  */
2330/* for pending interrupts after doing so.  */
2331_spentry(bind_interrupt_level_0)
2332        __(ldr temp1,[rcontext,#tcr.tlb_pointer])
2333        __(ldr temp0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2334        __(ldr imm0,[rcontext,#tcr.db_link])
2335        __(cmp temp0,#0)
2336        __(mov imm1,#INTERRUPT_LEVEL_BINDING_INDEX)
2337        __(vpush1(temp0))
2338        __(vpush1(imm1))
2339        __(vpush1(imm0))
2340        __(mov imm0,#0)
2341        __(str imm0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2342        __(str vsp,[rcontext,#tcr.db_link])
2343        __(bxeq lr)
2344        __(ldrlt temp0,[rcontext,#tcr.interrupt_pending])
2345        __(cmp temp0,#0)
2346        __(uuo_interrupt_now(gt))
2347        __(bx lr)
2348       
2349/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect */
2350/* of disabling interrupts.)  */
2351_spentry(bind_interrupt_level_m1)
2352        __(mov imm2,#-fixnumone)
2353        __(mov imm1,#INTERRUPT_LEVEL_BINDING_INDEX)
2354        __(ldr temp1,[rcontext,#tcr.tlb_pointer])
2355        __(ldr temp0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2356        __(ldr imm0,[rcontext,#tcr.db_link])
2357        __(vpush1(temp0))
2358        __(vpush1(imm1))
2359        __(vpush1(imm0))
2360        __(str imm2,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2361        __(str vsp,[rcontext,tcr.db_link])
2362        __(bx lr)
2363       
2364
2365/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
2366/* do what _SPbind_interrupt_level_0 does  */
2367_spentry(bind_interrupt_level)
2368        __(cmp arg_z,#0)
2369        __(mov imm1,#INTERRUPT_LEVEL_BINDING_INDEX)
2370        __(ldr temp1,[rcontext,#tcr.tlb_pointer])
2371        __(ldr temp0,[temp1,#INTERRUPT_LEVEL_BINDING_INDEX])
2372        __(ldr imm0,[rcontext,#tcr.db_link])
2373        __(beq _SPbind_interrupt_level_0)
2374        __(vpush1(temp0))
2375        __(vpush1(imm1))
2376        __(vpush1(imm0))
2377        __(str arg_z,[temp1,INTERRUPT_LEVEL_BINDING_INDEX])
2378        __(str vsp,[rcontext,#tcr.db_link])
2379        __(bx lr)
2380
2381/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
2382/* non-negative, check for pending interrupts.  This is often called in */
2383/* a context where nargs is significant, so save and restore nargs around */
2384/* any interrupt polling  */
2385         
2386_spentry(unbind_interrupt_level)
2387        __(ldr imm0,[rcontext,#tcr.flags])
2388        __(ldr temp2,[rcontext,#tcr.tlb_pointer])
2389        __(tst imm0,#1<<TCR_FLAG_BIT_PENDING_SUSPEND)
2390        __(ldr imm0,[rcontext,#tcr.db_link])
2391        __(ldr temp0,[temp2,#INTERRUPT_LEVEL_BINDING_INDEX])
2392        __(bne 5f)
23930:     
2394        __(ldr temp1,[imm0,#binding.val])
2395        __(ldr imm0,[imm0,#binding.link])
2396        __(str temp1,[temp2,#INTERRUPT_LEVEL_BINDING_INDEX])
2397        __(str imm0,[rcontext,#tcr.db_link])
2398        __(cmp temp0,#0)
2399        __(bxge lr)
2400        __(cmp temp1,#0)
2401        __(bxlt lr)
2402        __(check_enabled_pending_interrupt(imm0))
2403        __(bx lr)
24045:       /* Missed a suspend request; force suspend now if we're restoring
2405          interrupt level to -1 or greater */
2406        __(cmp temp0,#-2<<fixnumshift)
2407        __(bne 0b)
2408        __(ldr imm0,[imm1,#binding.val])
2409        __(cmp imm0,temp0)
2410        __(beq 0b)
2411        __(mov imm0,#1<<fixnumshift)
2412        __(str imm0,[temp2,INTERRUPT_LEVEL_BINDING_INDEX])
2413        __(suspend_now())
2414        __(b 0b)
2415 
2416 
2417/* arg_x = array, arg_y = i, arg_z = j. Typecheck everything.
2418    We don't know whether the array is alleged to be simple or
2419   not, and don't know anythng about the element type.  */
2420_spentry(aref2)
2421        __(trap_unless_fixnum(arg_y))
2422        __(trap_unless_fixnum(arg_z))
2423        __(extract_typecode(imm2,arg_x))
2424        __(cmp imm2,#subtag_arrayH)
2425        __(ldreq imm1,[arg_x,#arrayH.rank])
2426        __(cmpeq imm1,#2<<fixnumshift)
2427        __(uuo_error_reg_not_xtype(ne,arg_x,xtype_array2d))
2428        /* It's a 2-dimensional array.  Check bounds */
2429        __(ldr imm0,[arg_x,#arrayH.dim0])
2430        __(cmp arg_y,imm0)
2431        __(uuo_error_array_bounds(hs,arg_y,arg_x))
2432        __(ldr imm0,[arg_x,#arrayH.dim0+node_size])
2433        __(cmp arg_z,imm0)
2434        __(uuo_error_array_bounds(hs,arg_z,arg_x))
2435        __(unbox_fixnum(imm0,imm0))
2436        __(mul temp0,arg_y,imm0) /* no MLA on ARMv5 */
2437        __(add arg_z,arg_z,temp0)
2438        /* arg_z is now row-major-index; get data vector and
2439           add in possible offset */
2440        __(mov arg_y,arg_x)
24410:      __(ldr imm0,[arg_y,#arrayH.displacement])
2442        __(ldr arg_y,[arg_y,#arrayH.data_vector])
2443        __(extract_subtag(imm1,arg_y))
2444        __(cmp imm1,#subtag_vectorH)
2445        __(add arg_z,arg_z,imm0)
2446        __(bgt C(misc_ref_common))
2447        __(b 0b)
2448 
2449/* temp0 = array, arg_x = i, arg_y = j, arg_z = k */
2450_spentry(aref3)
2451        __(trap_unless_fixnum(arg_x))
2452        __(trap_unless_fixnum(arg_y))
2453        __(trap_unless_fixnum(arg_z))
2454        __(extract_typecode(imm2,temp0))
2455        __(mov imm1,#0)
2456        __(cmp imm2,#subtag_arrayH)
2457        __(ldreq imm1,[temp0,#arrayH.rank])
2458        __(cmp imm1,#3<<fixnumshift)
2459        __(uuo_error_reg_not_xtype(ne,temp0,xtype_array3d))
2460        /* It's a 3-dimensional array.  Check bounds */
2461        __(ldr imm2,[temp0,arrayH.dim0+(node_size*2)])
2462        __(ldr imm1,[temp0,#arrayH.dim0+node_size])
2463        __(ldr imm0,[temp0,#arrayH.dim0])
2464        __(cmp arg_z,imm2)
2465        __(uuo_error_array_bounds(hs,arg_z,temp0))
2466        __(cmp arg_y,imm1)
2467        __(uuo_error_array_bounds(hs,arg_y,temp0))
2468        __(cmp arg_x,imm0)
2469        __(uuo_error_array_bounds(hs,arg_x,temp0))
2470        __(unbox_fixnum(imm2,imm2))
2471        __(unbox_fixnum(imm1,imm1))
2472        __(mul arg_y,imm2,arg_y)
2473        __(mul imm1,imm2,imm1)
2474        __(mul arg_x,imm1,arg_x)
2475        __(add arg_z,arg_z,arg_y)
2476        __(add arg_z,arg_z,arg_x)
2477        __(mov arg_y,temp0)
24780:      __(ldr arg_x,[arg_y,#arrayH.displacement])
2479        __(ldr arg_y,[arg_y,#arrayH.data_vector])
2480        __(extract_subtag(imm1,arg_y))
2481        __(cmp imm1,#subtag_vectorH)
2482        __(add arg_z,arg_x,arg_z)
2483        __(bgt C(misc_ref_common))
2484        __(b 0b)
2485
2486
2487
2488
2489/* As for aref2 above, but temp = array, arg_x = i, arg_y = j, arg_z = newval */
2490_spentry(aset2)
2491        __(extract_typecode(imm0,temp0))
2492        __(cmp imm0,#subtag_arrayH)
2493        __(ldreq imm0,[temp0,#arrayH.rank])
2494        __(cmpeq imm0,#2<<fixnumshift)
2495        __(uuo_error_reg_not_xtype(ne,temp0,xtype_array2d))
2496        __(trap_unless_fixnum(arg_x))
2497        __(trap_unless_fixnum(arg_y))
2498        /* It's a 2-dimensional array.  Check bounds */
2499        __(ldr imm0,[temp0,#arrayH.dim0])
2500        __(cmp arg_x,imm0)
2501        __(uuo_error_array_bounds(hs,arg_x,temp0))
2502        __(ldr imm0,[temp0,#arrayH.dim0+node_size])
2503        __(cmp arg_y,imm0)
2504        __(uuo_error_array_bounds(hs,arg_y,temp0))
2505        __(unbox_fixnum(imm0,imm0))
2506        __(mul temp1,arg_x,imm0)
2507        __(add arg_y,arg_y,temp1)
2508        /* arg_y is now row-major-index; get data vector and
2509           add in possible offset */
2510        __(mov arg_x,temp0)
25110:      __(ldr imm0,[arg_x,#arrayH.displacement])
2512        __(ldr arg_x,[arg_x,#arrayH.data_vector])
2513        __(extract_subtag(imm1,arg_x))
2514        __(cmp imm1,#subtag_vectorH)
2515        __(add arg_y,arg_y,imm0)
2516        __(bgt C(misc_set_common))
2517        __(b 0b)
2518
2519                 
2520/* temp1 = array, temp0 = i, arg_x = j, arg_y = k, arg_z = new */       
2521_spentry(aset3)
2522        __(extract_typecode(imm0,temp1))
2523        __(cmp imm0,#subtag_arrayH)
2524        __(ldreq imm0,[temp1,#arrayH.rank])
2525        __(cmpeq imm0,#3<<fixnumshift)
2526        __(uuo_error_reg_not_xtype(ne,temp1,xtype_array3d))
2527        __(trap_unless_fixnum(temp0))
2528        __(trap_unless_fixnum(arg_x))
2529        __(trap_unless_fixnum(arg_y))
2530        /* It's a 3-dimensional array.  Check bounds */
2531        __(ldr imm2,[temp1,#arrayH.dim0+(node_size*2)])
2532        __(ldr imm1,[temp1,#arrayH.dim0+node_size])
2533        __(ldr imm0,[temp1,#arrayH.dim0])
2534        __(cmp arg_y,imm2)
2535        __(uuo_error_array_bounds(hs,arg_y,temp1))
2536        __(cmp arg_x,imm1)
2537        __(uuo_error_array_bounds(hs,arg_x,temp1))
2538        __(unbox_fixnum(imm1,imm1))
2539        __(cmp temp0,imm0)
2540        __(uuo_error_array_bounds(hs,temp0,temp1))
2541        __(mul arg_x,imm2,arg_x)
2542        __(mul imm1,imm2,imm1)
2543        __(mul temp0,imm1,temp0)
2544        __(add arg_y,arg_y,arg_x)
2545        __(add arg_y,arg_y,temp0)
2546        __(mov arg_x,temp1)
25470:      __(ldr temp0,[arg_x,#arrayH.displacement])
2548        __(ldr arg_x,[arg_x,#arrayH.data_vector])
2549        __(extract_subtag(imm1,arg_x))
2550        __(cmp imm1,#subtag_vectorH)
2551        __(add arg_y,arg_y,temp0)
2552        __(bgt C(misc_set_common))
2553        __(b 0b)
2554
2555
2556/* Treat the last (- nargs imm0) values on the vstack as keyword/value  */
2557/* pairs.  There'll be arg_z keyword arguments.  arg_y contains flags  */
2558/* that indicate whether &allow-other-keys was specified and whether  */
2559/* or not to leave the keyword/value pairs on the vstack for an &rest  */
2560/* argument.  Element 2 of the function in fn contains a vector of keyword.  */
2561/* If the number of arguments is greater than imm0, the difference must  */
2562/* be even.  */
2563/* All arg regs have been vpushed and the calling function has built a */
2564/* stack frame.  next_method_context must be preserved, as must the incoming */
2565/* key/value pairs and their number if we're going to make an &rest arg. */
2566           
2567
2568define(`keyword_flags',`arg_y')
2569define(`key_value_count',`arg_z')
2570
2571define(`keyword_flag_allow_other_keys',`(fixnumone<<0)')
2572define(`keyword_flag_seen_allow_other_keys',`(fixnumone<<1)')
2573define(`keyword_flag_rest',`(fixnumone<<2)')
2574define(`keyword_flag_unknown_keyword_seen',`(fixnumone<<3)')
2575define(`keyword_flag_current_aok',`(fixnumone<<4)')
2576
2577_spentry(keyword_bind)
2578        new_local_labels()       
2579        __(subs key_value_count,nargs,imm0)
2580        __(movmi key_value_count,#0)
2581        __(tst key_value_count,#fixnumone)
2582        __(bne local_label(odd_keywords))
2583        __(mov imm1,key_value_count,lsl #num_subtag_bits-fixnumshift)
2584        __(orr imm1,imm1,subtag_u32_vector)
2585        __(add imm0,key_value_count,#dnode_size) /* we know  count is even */
2586        __(stack_allocate_zeroed_ivector(imm1,imm0))
2587        __(mov imm0,#subtag_simple_vector)
2588        __(strb imm0,[sp])
2589        /* Copy key/value pairs in reverse order from the vstack to
2590           the gvector we just created on the cstack. */
2591        __(add imm0,vsp,key_value_count) /* src, predecrement */
2592        __(add imm1,sp,#node_size)       /* dest, postincrement */
2593        __(mov temp2,key_value_count)
2594        __(b 1f)
25950:      __(ldr arg_x,[imm0,#-node_size]!)
2596        __(str arg_x,[imm1],#node_size)
25971:      __(subs temp2,temp2,#fixnumone)
2598        __(bge 0b)
2599        /* Discard the key/value pairs from the vstack. */
2600        __(add vsp,vsp,key_value_count)
2601        __(ldr temp2,[fn,#misc_data_offset+(2*node_size)])
2602        __(getvheader(imm0,temp2))
2603        __(mov imm0,imm0,lsr #num_subtag_bits)
2604        __(mov temp0,vsp)
2605        __(mov imm1,#nil_value)
2606        /* Push a pair of NILs (value, supplied-p) for each defined keyword */
2607        __(b 3f)
26082:      __(vpush1(imm1))
2609        __(vpush1(imm1))
26103:      __(subs imm0,imm0,#1)
2611        __(bge 2b)
2612        /* Save nargs and temp1 so that we can use them in the loop(s) */
2613        __(stmdb vsp!,{imm2,temp1})
2614        /* For each provided key/value pair: if the key is :allow-other-keys
2615           and that hasn't been seen before, note that it's been seen and
2616           if the value is non-nil set the allow-other-keys bit in flags.
2617           Then search for the key in the defined keys vector.  If it's
2618           not found, note that an undefined keyword was seen by setting
2619           a bit in keyword_flags ; if it is found, use its position to
2620           index the table of value/supplied-p pairs that we pushed above.
2621           If the supplied-p var is already set, do nothing; otherwise,
2622           set the supplied-p var and value.
2623           When done, signal an error if we got an unknown keyword, or
2624           either copy the supplied key/value pairs back to the vstack
2625           if we're going to cons an &rest arg or discard them if we aren't.
2626        */
2627        __(mov imm2,#0)
2628        __(b local_label(nextvalpairtest))
2629local_label(nextvalpairloop):   
2630        __(add temp1,sp,#4)
2631        __(ldr temp1,[temp1,imm2])
2632        __(ref_nrs_symbol(imm1,kallowotherkeys,imm1))
2633        __(cmp temp1,imm1)
2634        __(orreq keyword_flags,keyword_flags,#keyword_flag_current_aok)
2635        __(tsteq keyword_flags,#keyword_flag_seen_allow_other_keys)
2636        __(bne local_label(current_key_allow_other_keys_handled))
2637        __(orr keyword_flags,keyword_flags,#keyword_flag_seen_allow_other_keys)
2638        /* Fortunately, we know what the keyword is.  Need to check the
2639           value here, and don't have a lot of free registers ... */
2640        __(add temp1,sp,#8)
2641        __(ldr temp1,[temp1,imm2])
2642        __(cmp temp1,#nil_value)
2643        __(orrne keyword_flags,keyword_flags,#keyword_flag_allow_other_keys)
2644        __(mov temp1,imm1)      /* from comparison above */
2645local_label(current_key_allow_other_keys_handled):
2646        __(getvheader(imm0,temp2))
2647        __(header_length(arg_x,imm0))
2648        __(add imm0,arg_x,#misc_data_offset)
2649        __(b local_label(defined_keyword_compare_test))
2650local_label(defined_keyword_compare_loop):     
2651        __(ldr arg_x,[temp2,imm0])
2652        __(cmp arg_x,temp1)
2653        __(subeq imm0,imm0,#misc_data_offset)
2654        __(beq local_label(defined_keyword_found))
2655local_label(defined_keyword_compare_test):     
2656        __(sub imm0,imm0,#node_size)
2657        __(cmp imm0,#misc_data_offset)
2658        __(bge local_label(defined_keyword_compare_loop))
2659        /* keyword wasn't defined.  Note that ... */
2660        __(tst keyword_flags,#keyword_flag_current_aok)
2661        __(bicne keyword_flags,#keyword_flag_current_aok)
2662        __(orreq keyword_flags,keyword_flags,#keyword_flag_unknown_keyword_seen)
2663        __(b local_label(nextkeyvalpairnext))
2664local_label(defined_keyword_found):     
2665        __(sub imm0,temp0,imm0,lsl #1)
2666        __(ldr arg_x,[imm0,#-8])
2667        __(cmp arg_x,#nil_value) /* seen this keyword yet ? */
2668        __(bne local_label(nextkeyvalpairnext))
2669        __(add arg_x,arg_x,#t_offset)
2670        __(str arg_x,[imm0,#-8])
2671        __(add temp1,sp,#8)
2672        __(ldr temp1,[temp1,imm2])
2673        __(str temp1,[imm0,#-4])
2674local_label(nextkeyvalpairnext):
2675        __(add imm2,imm2,#8)
2676local_label(nextvalpairtest):   
2677        __(cmp imm2,key_value_count)
2678        __(bne local_label(nextvalpairloop))
2679        __(ldmia vsp!,{imm2,temp1})
2680        /* If unknown keywords and that's not allowed, signal error.
2681           Otherwise, discard the stack-consed vector and return,
2682           possibly after having copied the vector's contents back
2683           to the vstack so that an &rest arg can be constructed.
2684        */
2685        __(tst keyword_flags,#keyword_flag_unknown_keyword_seen)
2686        __(beq 0f)
2687        __(tst keyword_flags,#keyword_flag_allow_other_keys)
2688        __(beq local_label(badkeys))
26890:      __(tst keyword_flags,#keyword_flag_rest)
2690        __(beq local_label(discard_stack_vector))
2691        __(mov imm0,#0)
2692        __(add temp2,sp,#node_size)
2693        __(b 2f)
26941:      __(ldr arg_x,[temp2],#node_size)
2695        __(vpush1(arg_x))
2696        __(add imm0,imm0,#fixnumone)
26972:      __(cmp imm0,key_value_count)
2698        __(bne 1b)
2699local_label(discard_stack_vector):     
2700        __(add key_value_count,key_value_count,#dnode_size)
2701        __(add sp,sp,key_value_count)
2702        __(bx lr)               /* it's finally over ! */
2703
2704local_label(badkeys):   /* Disturbingly similar to the &rest case */
2705        __(mov nargs,#0)
2706        __(add temp2,sp,#node_size)
2707        __(mov vsp,temp0)
2708        __(b 1f)
27090:      __(ldr arg_x,[temp2],#node_size)
2710        __(vpush1(arg_x))
2711        __(add nargs,nargs,#fixnumone)
27121:      __(cmp nargs,key_value_count)
2713        __(bne 0b)
2714        /* Lose the stack vector */
2715        __(add key_value_count,key_value_count,#dnode_size)
2716        __(add sp,sp,key_value_count)
2717local_label(error_exit):               
2718        __(bl _SPconslist)
2719        __(mov arg_y,#XBADKEYS)
2720        __(set_nargs(2))
2721        __(b _SPksignalerr)
2722local_label(odd_keywords):       
2723        __(mov nargs,key_value_count)
2724        __(b local_label(error_exit))
2725
2726        .globl C(__aeabi_uidivmod)               
2727_spentry(udiv32)
2728        __(cmp imm1,#0)
2729        __(moveq arg_z,#XDIVZRO)
2730        __(moveq nargs,#1<<fixnumshift)
2731        __(beq _SPksignalerr)
2732        __(stmdb vsp!,{arg_z,arg_y,arg_x,temp0,temp1,temp2})
2733        __(str vsp,[rcontext,#tcr.save_vsp])
2734        __(mov arg_z,rcontext)
2735        __(ldr arg_y,[rcontext,#tcr.last_lisp_frame])
2736        __(build_lisp_frame(r3))
2737        __(str sp,[arg_z,#tcr.last_lisp_frame])
2738        __(str allocptr,[arg_z,#tcr.save_allocptr])
2739        __(mov r3,#TCR_STATE_FOREIGN)
2740        __(str r3,[arg_z,#tcr.valence])
2741        __(mov r3,#0)
2742        __(bl C(__aeabi_uidivmod))
2743        __(mov rcontext,arg_z)
2744        __(str arg_y,[rcontext,#tcr.last_lisp_frame])
2745        __(mov allocptr,#VOID_ALLOCPTR)
2746        __(mov fn,#0)
2747        __(mov temp2,#0)
2748        __(mov temp1,#0)
2749        __(mov temp0,#0)
2750        __(mov arg_x,#TCR_STATE_LISP)
2751        __(str arg_x,[rcontext,#tcr.valence])
2752        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
2753        __(ldm vsp!,{arg_z,arg_y,arg_x,temp0,temp1,temp2})
2754        __(ldr fn,[sp,#lisp_frame.savefn])
2755        __(ldr lr,[sp,#lisp_frame.savelr])
2756        __(discard_lisp_frame())
2757        __(bx lr)
2758
2759_spentry(sdiv32)
2760        __(cmp imm1,#0)
2761        __(moveq arg_z,#XDIVZRO)
2762        __(moveq nargs,#1<<fixnumshift)
2763        __(beq _SPksignalerr)
2764        __(stmdb vsp!,{arg_z,arg_y,arg_x,temp0,temp1,temp2})
2765        __(str vsp,[rcontext,#tcr.save_vsp])
2766        __(mov arg_z,rcontext)
2767        __(ldr arg_y,[rcontext,#tcr.last_lisp_frame])
2768        __(build_lisp_frame(r3))
2769        __(str sp,[arg_z,#tcr.last_lisp_frame])
2770        __(str allocptr,[arg_z,#tcr.save_allocptr])
2771        __(mov r3,#TCR_STATE_FOREIGN)
2772        __(str r3,[arg_z,#tcr.valence])
2773        __(mov r3,#0)
2774        __(bl C(__aeabi_idivmod))
2775        __(mov rcontext,arg_z)
2776        __(str arg_y,[rcontext,#tcr.last_lisp_frame])
2777        __(mov allocptr,#VOID_ALLOCPTR)
2778        __(mov fn,#0)
2779        __(mov temp2,#0)
2780        __(mov temp1,#0)
2781        __(mov temp0,#0)
2782        __(mov arg_x,#TCR_STATE_LISP)
2783        __(str arg_x,[rcontext,#tcr.valence])
2784        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
2785        __(ldm vsp!,{arg_z,arg_y,arg_x,temp0,temp1,temp2})
2786        __(ldr fn,[sp,#lisp_frame.savefn])
2787        __(ldr lr,[sp,#lisp_frame.savelr])
2788        __(discard_lisp_frame())
2789        __(bx lr)
2790       
2791
2792               
2793_spentry(eabi_ff_call)
2794        __(ldr arg_y,[rcontext,#tcr.last_lisp_frame])
2795        __(stmdb vsp!,{arg_y,arg_x,temp0,temp1,temp2})
2796        __(str vsp,[rcontext,#tcr.save_vsp])
2797/* There's a u32 vector on top of the stack ; its first data word points
2798   to the previous stack object.  The 4 words at the bottom of the vector
2799   are reserved for a lisp frame, which we construct carefully ... */
2800        __(mov imm0,#lisp_frame_marker)
2801        __(mov imm1,#0)
2802        __(ldr temp0,[sp,#4])
2803        __(sub temp0,temp0,#lisp_frame.size)
2804        __(str imm0,[temp0,#lisp_frame.marker])
2805        __(ldr imm0,[sp,#0])       
2806        __(str imm1,[temp0,#lisp_frame.savefn])
2807        __(str imm1,[temp0,#lisp_frame.savelr])
2808        __(sub imm0,imm0,#(lisp_frame.size/4)<<num_subtag_bits)
2809        __(str vsp,[temp0,#lisp_frame.savevsp])
2810        __(str imm0,[sp,#0])
2811        __(str lr,[temp0,#lisp_frame.savelr])
2812        __(str fn,[temp0,#lisp_frame.savefn])
2813        __(str allocptr,[rcontext,#tcr.save_allocptr])
2814        __(str temp0,[rcontext,#tcr.last_lisp_frame])
2815        __(mov temp0,rcontext)
2816        __(test_fixnum(arg_z))
2817        __(moveq imm1,arg_z,asr #fixnumshift)
2818        __(ldrne imm1,[arg_z,#misc_data_offset])
2819        __(mov imm0,#TCR_STATE_FOREIGN)
2820        __(str imm0,[rcontext,#tcr.valence])
2821        __(mov r4,imm1)
2822        __(add sp,sp,#dnode_size)
2823        __(ldmia sp!,{r0,r1,r2,r3})
2824        __(blx r4) 
2825        __(mov temp1,#0)
2826        __(mov temp2,#0)
2827        __(mov arg_z,#0)
2828        __(mov arg_y,#0)
2829        __(mov arg_x,#0)
2830        __(mov fn,#0)
2831        __(mov allocptr,#VOID_ALLOCPTR)
2832        __(mov rcontext,temp0)
2833        __(ldr sp,[rcontext,#tcr.last_lisp_frame])
2834        __(str fn,[rcontext,#tcr.valence])
2835        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
2836        __(restore_lisp_frame(temp0))
2837        __(ldmia vsp!,{arg_y,arg_x,temp0,temp1,temp2})
2838        __(str arg_y,[rcontext,#tcr.last_lisp_frame])
2839        __(check_pending_interrupt(temp2))
2840        __(bx lr)
2841       
2842       
2843
2844_spentry(debind)
2845        new_local_labels()
2846        __(mov temp0,vsp)
2847        __(mov temp1,arg_z)
2848        __(ands imm0,nargs,#0xff)
2849        __(mov arg_y,#nil_value)
2850        __(b local_label(req_test))
2851local_label(req_loop): 
2852        __(cmp arg_reg,#nil_value)
2853        __(extract_lisptag(imm1,arg_reg))
2854        __(beq local_label(toofew))
2855        __(cmp imm1,#tag_list)
2856        __(bne local_label(badlist))
2857        __(subs imm0,imm0,#1)
2858        __(_car(arg_x,arg_reg))
2859        __(_cdr(arg_reg,arg_reg))
2860        __(vpush1(arg_x))
2861local_label(req_test):
2862        __(bne local_label(req_loop))
2863        __(mov imm0,#0xff)
2864        __(ands imm0,imm0,nargs,lsr #8)
2865        __(beq local_label(rest_keys))
2866        __(tst nargs,#mask_initopt)
2867        __(bne local_label(opt_supp))
2868        /* 'simple' &optionals:  no supplied-p, default to nil.   */
2869local_label(simple_opt_loop):
2870        __(cmp arg_reg,#nil_value)
2871        __(extract_lisptag(imm1,arg_reg))
2872        __(beq local_label(default_simple_opt))
2873        __(cmp imm1,#tag_list)
2874        __(bne local_label(badlist))
2875        __(subs imm0,imm0,#1)
2876        __(_car(arg_x,arg_reg))
2877        __(_cdr(arg_reg,arg_reg))
2878        __(vpush1(arg_x))
2879        __(bne local_label(simple_opt_loop))
2880        __(b local_label(rest_keys))
2881local_label(default_simple_opt):       
2882        __(subs imm0,imm0,#1)
2883        __(vpush1(arg_y))
2884        __(bne local_label(default_simple_opt))
2885        __(b local_label(rest_keys))
2886local_label(opt_supp):   
2887        __(cmp arg_reg,#nil_value)
2888        __(extract_lisptag(imm1,arg_reg))
2889        __(beq local_label(default_hard_opt))
2890        __(cmp imm1,#tag_list)
2891        __(bne local_label(badlist))
2892        __(subs imm0,imm0,#1)
2893        __(_car(arg_x,arg_reg))
2894        __(_cdr(arg_reg,arg_reg))
2895        __(vpush1(arg_x))
2896        __(add arg_x,arg_y,#t_offset)
2897        __(vpush1(arg_x))
2898        __(bne local_label(opt_supp))
2899        __(b local_label(rest_keys))
2900local_label(default_hard_opt): 
2901        __(subs imm0,imm0,#1)
2902        __(vpush1(arg_y))
2903        __(vpush1(arg_y))
2904        __(bne local_label(default_hard_opt))
2905local_label(rest_keys): 
2906        __(tst nargs,#mask_restp)
2907        __(bne local_label(have_rest))
2908        __(tst nargs,#mask_keyp)
2909        __(bne local_label(have_keys))
2910        __(cmp arg_reg,#nil_value)
2911        __(bne local_label(toomany))
2912        __(bx lr)
2913local_label(have_rest): 
2914        __(vpush1(arg_reg))
2915        __(tst nargs,#mask_keyp)
2916        __(bne local_label(have_keys))
2917        __(bx lr)
2918local_label(have_keys): 
2919        __(mov imm0,#256)
2920        __(mov arg_y,arg_reg)
2921local_label(count_keys_loop):   
2922        __(cmp arg_y,#nil_value)
2923        __(beq local_label(counted_keys))
2924        __(subs imm0,imm0,#1)
2925        __(bmi local_label(toomany))
2926        __(extract_lisptag(imm1,arg_y))
2927        __(cmp imm1,#tag_list)
2928        __(bne local_label(badlist))
2929        __(_cdr(arg_y,arg_y))
2930        __(cmp arg_y,#nil_value)
2931        __(extract_lisptag(imm1,arg_y))
2932        __(beq local_label(badkeys))
2933        __(cmp imm1,#tag_list)
2934        __(bne local_label(badlist))
2935        __(_cdr(arg_y,arg_y))
2936        __(b local_label(count_keys_loop))
2937local_label(counted_keys):     
2938        /* We've got a proper, even-length list of key/value pairs in  */
2939        /* arg_reg. For each keyword var in the lambda-list, push a pair  */
2940        /* of NILs on the vstack.  (We've also cdred down arg_y until it */
2941        /* contains NIL.) */
2942        __(mov imm0,#0xff)
2943        __(ands imm0,imm0,nargs,lsr #16)
2944        __(mov imm1,vsp)
2945        __(b local_label(push_pair_test))
2946local_label(push_pair_loop):
2947        __(subs imm0,imm0,#1)
2948        __(vpush1(arg_y))
2949        __(vpush1(arg_y))
2950local_label(push_pair_test):   
2951        __(bne local_label(push_pair_loop))
2952        __(b local_label(provided_key_loop))
2953       
2954local_label(next_provided_key): 
2955        __(_car(arg_x,arg_reg))
2956        __(ref_nrs_symbol(imm0,kallowotherkeys,imm0))
2957        __(cmp arg_x,imm0)
2958        __(bne local_label(not_aok))
2959        __(orr nargs,nargs,#mask_aok_this)
2960        __(tst nargs,#mask_aok_seen)
2961        __(bne local_label(not_aok))
2962        __(_cdr(arg_x,arg_reg))
2963        __(_car(arg_x,arg_x))
2964        __(orr nargs,nargs,#mask_aok_seen)
2965        __(cmp arg_x,#nil_value)
2966        __(orrne nargs,nargs,#mask_aok)
2967        __(_car(arg_x,arg_reg))
2968local_label(not_aok):   
2969        __(getvheader(imm0,keyvect_reg))
2970        __(header_length(arg_y,imm0))
2971        __(add imm0,arg_y,#misc_data_offset)
2972        __(b local_label(match_key_test))
2973local_label(match_key_loop):   
2974        __(ldr arg_y,[keyvect_reg,imm0])
2975        __(cmp arg_x,arg_y)
2976        __(bne local_label(match_key_test))
2977        __(sub imm0,imm0,#misc_data_offset)
2978        __(sub imm0,imm1,imm0,lsl #1)
2979        __(ldr arg_y,[imm0,#-2*node_size])
2980        __(cmp arg_y,#nil_value)
2981        __(bne local_label(provided_key_done))
2982        __(_cdr(arg_x,arg_reg))
2983        __(_car(arg_x,arg_x))
2984        __(str arg_x,[imm0,#-node_size])
2985        __(mov arg_x,#nil_value)
2986        __(add arg_x,arg_x,#t_offset)
2987        __(str arg_x,[imm0,#-2*node_size])
2988        __(b local_label(provided_key_done))
2989local_label(match_key_test):   
2990        __(sub imm0,imm0,#node_size)
2991        __(cmp imm0,#misc_data_offset)
2992        __(bge local_label(match_key_loop))
2993        __(tst nargs,#mask_aok_this)
2994        __(bic nargs,nargs,#mask_aok_this)
2995        __(orreq nargs,nargs,#mask_unknown_keyword_seen)
2996local_label(provided_key_done): 
2997        __(_cdr(arg_reg,arg_reg))
2998        __(_cdr(arg_reg,arg_reg))
2999local_label(provided_key_loop):
3000        __(cmp arg_reg,#nil_value)
3001        __(bne local_label(next_provided_key))
3002        __(tst nargs,#mask_unknown_keyword_seen)
3003        __(bxeq lr)
3004        __(tst nargs,#mask_aok)
3005        __(bxne lr)
3006local_label(badkeys):
3007        __(mov arg_y,#XBADKEYS)
3008        __(b local_label(destructure_error))
3009local_label(toomany):   
3010        __(mov arg_y,#XCALLTOOMANY)
3011        __(b local_label(destructure_error))
3012local_label(toofew):   
3013        __(mov arg_y,#XCALLTOOFEW)
3014        __(b local_label(destructure_error))
3015local_label(badlist):   
3016        __(mov arg_y,#XCALLNOMATCH)
3017local_label(destructure_error): 
3018        __(mov vsp,temp0)
3019        __(mov arg_z,temp1)       
3020        __(set_nargs(2))
3021        __(b _SPksignalerr)
3022       
3023_spentry(eabi_callback)
3024        __(stmdb sp!,{r0,r1,r2,r3})
3025        __(mov r0,sp)
3026        __(sub sp,sp,#2*node_size) /* room for result */
3027        __(stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr})
3028        __(mov r4,r0)
3029        __(box_fixnum(r5,r12))
3030        __(ref_global(r12,get_tcr,r0))
3031        __(mov r0,#1)
3032        __(blx r12)
3033        __(mov rcontext,r0)
3034        __(tst sp,#4)
3035        __(mov imm2,sp)
3036        __(strne imm2,[sp,#-4]!)
3037        __(streq imm2,[sp,#-8]!)
3038        __(ldr imm2,[rcontext,#tcr.last_lisp_frame])
3039        __(sub imm0,imm2,sp)
3040        __(add imm0,imm0,#node_size)
3041        __(mov imm0,imm0,lsl #num_subtag_bits-word_shift)
3042        __(orr imm0,imm0,#subtag_u32_vector)
3043        __(stmdb sp!,{imm0,imm2})
3044        __(mov arg_x,#0)
3045        __(mov temp0,#0)
3046        __(mov temp1,#0)
3047        __(mov temp2,#0)
3048        __(mov allocptr,#VOID_ALLOCPTR)
3049        __(mov fn,#0)
3050        __(ldr vsp,[rcontext,#tcr.save_vsp])
3051        __(mov imm0,#TCR_STATE_LISP)
3052        __(str imm0,[rcontext,#tcr.valence])
3053        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
3054        __(set_nargs(2))
3055        __(ref_nrs_symbol(fname,callbacks,imm0))
3056        __(ldr nfn,[fname,#symbol.fcell])
3057        __(ldr lr,[nfn,#_function.entrypoint])
3058        __(blx lr)
3059        __(str vsp,[rcontext,#tcr.save_vsp])
3060        __(ldr imm1,[sp,#4])
3061        __(str imm1,[rcontext,#tcr.last_lisp_frame])
3062        __(str allocptr,[rcontext,#tcr.save_allocptr])
3063        __(mov imm0,#TCR_STATE_FOREIGN)
3064        __(str imm0,[rcontext,#tcr.valence])
3065        __(ldr sp,[sp,#node_size*2])   /* drop the ivector that hides foreign stack contents and restore (possibly misaligned) sp */
3066        __(ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr})
3067        __(ldmia sp!,{r0,r1})
3068        __(add sp,sp,#4*node_size)
3069        __(bx lr)
3070       
3071/*  EOF, basically  */
3072       
3073_exportfn(C(misc_ref_common))
3074        __(adr imm0,(local_label(misc_ref_jmp)))
3075        __(ldr pc,[imm0,imm1,lsl #2])
3076
3077local_label(misc_ref_jmp):         
3078        /* 00-0*/
3079        .long local_label(misc_ref_invalid) /* 00 even_fixnum  */
3080       
3081        .long local_label(misc_ref_invalid) /* 01 cons  */
3082        .long local_label(misc_ref_invalid) /* 02 nodeheader  */
3083        .long local_label(misc_ref_invalid) /* 03 imm  */
3084        .long local_label(misc_ref_invalid) /* 04 odd_fixnum  */
3085        .long local_label(misc_ref_invalid) /* 05 nil  */
3086        .long local_label(misc_ref_invalid) /* 06 misc  */
3087        .long local_label(misc_ref_u32) /* 07 bignum  */
3088        .long local_label(misc_ref_invalid) /* 08 even_fixnum  */
3089        .long local_label(misc_ref_invalid) /* 09 cons  */
3090        .long local_label(misc_ref_node) /* 0a ratio  */
3091        .long local_label(misc_ref_invalid) /* 0b imm  */
3092        .long local_label(misc_ref_invalid) /* 0c odd_fixnum  */
3093        .long local_label(misc_ref_invalid) /* 0d nil  */
3094        .long local_label(misc_ref_invalid) /* 0e misc  */
3095        .long local_label(misc_ref_u32) /* 0f single_float  */
3096        /* 10-1*/
3097        .long local_label(misc_ref_invalid) /* 10 even_fixnum  */
3098        .long local_label(misc_ref_invalid) /* 11 cons  */
3099        .long local_label(misc_ref_invalid) /* 12 nodeheader  */
3100        .long local_label(misc_ref_invalid) /* 13 imm  */
3101        .long local_label(misc_ref_invalid) /* 14 odd_fixnum  */
3102        .long local_label(misc_ref_invalid) /* 15 nil  */
3103        .long local_label(misc_ref_invalid) /* 16 misc  */
3104        .long local_label(misc_ref_u32) /* 17 double_float  */
3105        .long local_label(misc_ref_invalid) /* 18 even_fixnum  */
3106        .long local_label(misc_ref_invalid) /* 19 cons  */
3107        .long local_label(misc_ref_node) /* 1a complex  */
3108        .long local_label(misc_ref_invalid) /* 1b imm  */
3109        .long local_label(misc_ref_invalid) /* 1c odd_fixnum  */
3110        .long local_label(misc_ref_invalid) /* 1d nil  */
3111        .long local_label(misc_ref_invalid) /* 1e misc  */
3112        .long local_label(misc_ref_u32) /* 1f macptr  */
3113        /* 20-2*/
3114        .long local_label(misc_ref_invalid) /* 20 even_fixnum  */
3115        .long local_label(misc_ref_invalid) /* 21 cons  */
3116        .long local_label(misc_ref_node) /* 22 catch_frame  */
3117        .long local_label(misc_ref_invalid) /* 23 imm  */
3118        .long local_label(misc_ref_invalid) /* 24 odd_fixnum  */
3119        .long local_label(misc_ref_invalid) /* 25 nil  */
3120        .long local_label(misc_ref_invalid) /* 26 misc  */
3121        .long local_label(misc_ref_u32) /* 27 dead_macptr  */
3122        .long local_label(misc_ref_invalid) /* 28 even_fixnum  */
3123        .long local_label(misc_ref_invalid) /* 29 cons  */
3124        .long local_label(misc_ref_node) /* 2a function  */
3125        .long local_label(misc_ref_invalid) /* 2b imm  */
3126        .long local_label(misc_ref_invalid) /* 2c odd_fixnum  */
3127        .long local_label(misc_ref_invalid) /* 2d nil  */
3128        .long local_label(misc_ref_invalid) /* 2e misc  */
3129        .long local_label(misc_ref_u32) /* 2f code_vector  */
3130        /* 30-3*/
3131        .long local_label(misc_ref_invalid) /* 30 even_fixnum  */
3132        .long local_label(misc_ref_invalid) /* 31 cons  */
3133        .long local_label(misc_ref_node) /* 32 lisp_thread  */
3134        .long local_label(misc_ref_invalid) /* 33 imm  */
3135        .long local_label(misc_ref_invalid) /* 34 odd_fixnum  */
3136        .long local_label(misc_ref_invalid) /* 35 nil  */
3137        .long local_label(misc_ref_invalid) /* 36 misc  */
3138        .long local_label(misc_ref_u32) /* 37 creole  */
3139        .long local_label(misc_ref_invalid) /* 38 even_fixnum  */
3140        .long local_label(misc_ref_invalid) /* 39 cons  */
3141        .long local_label(misc_ref_node) /* 3a symbol  */
3142        .long local_label(misc_ref_invalid) /* 3b imm  */
3143        .long local_label(misc_ref_invalid) /* 3c odd_fixnum  */
3144        .long local_label(misc_ref_invalid) /* 3d nil  */
3145        .long local_label(misc_ref_invalid) /* 3e misc  */
3146        .long local_label(misc_ref_u32) /* 3f xcode_vector  */
3147        /* 40-4*/
3148        .long local_label(misc_ref_invalid) /* 40 even_fixnum  */
3149        .long local_label(misc_ref_invalid) /* 41 cons  */
3150        .long local_label(misc_ref_node) /* 42 lock  */
3151        .long local_label(misc_ref_invalid) /* 43 imm  */
3152        .long local_label(misc_ref_invalid) /* 44 odd_fixnum  */
3153        .long local_label(misc_ref_invalid) /* 45 nil  */
3154        .long local_label(misc_ref_invalid) /* 46 misc  */
3155        .long local_label(misc_ref_invalid) /* 47 immheader  */
3156        .long local_label(misc_ref_invalid) /* 48 even_fixnum  */
3157        .long local_label(misc_ref_invalid) /* 49 cons  */
3158        .long local_label(misc_ref_node) /* 4a hash_vector  */
3159        .long local_label(misc_ref_invalid) /* 4b imm  */
3160        .long local_label(misc_ref_invalid) /* 4c odd_fixnum  */
3161        .long local_label(misc_ref_invalid) /* 4d nil  */
3162        .long local_label(misc_ref_invalid) /* 4e misc  */
3163        .long local_label(misc_ref_invalid) /* 4f immheader  */
3164        /* 50-5*/
3165        .long local_label(misc_ref_invalid) /* 50 even_fixnum  */
3166        .long local_label(misc_ref_invalid) /* 51 cons  */
3167        .long local_label(misc_ref_node) /* 52 pool  */
3168        .long local_label(misc_ref_invalid) /* 53 imm  */
3169        .long local_label(misc_ref_invalid) /* 54 odd_fixnum  */
3170        .long local_label(misc_ref_invalid) /* 55 nil  */
3171        .long local_label(misc_ref_invalid) /* 56 misc  */
3172        .long local_label(misc_ref_invalid) /* 57 immheader  */
3173        .long local_label(misc_ref_invalid) /* 58 even_fixnum  */
3174        .long local_label(misc_ref_invalid) /* 59 cons  */
3175        .long local_label(misc_ref_node) /* 5a weak  */
3176        .long local_label(misc_ref_invalid) /* 5b imm  */
3177        .long local_label(misc_ref_invalid) /* 5c odd_fixnum  */
3178        .long local_label(misc_ref_invalid) /* 5d nil  */
3179        .long local_label(misc_ref_invalid) /* 5e misc  */
3180        .long local_label(misc_ref_invalid) /* 5f immheader  */
3181        /* 60-6*/
3182        .long local_label(misc_ref_invalid) /* 60 even_fixnum  */
3183        .long local_label(misc_ref_invalid) /* 61 cons  */
3184        .long local_label(misc_ref_node) /* 62 package  */
3185        .long local_label(misc_ref_invalid) /* 63 imm  */
3186        .long local_label(misc_ref_invalid) /* 64 odd_fixnum  */
3187        .long local_label(misc_ref_invalid) /* 65 nil  */
3188        .long local_label(misc_ref_invalid) /* 66 misc  */
3189        .long local_label(misc_ref_invalid) /* 67 immheader  */
3190        .long local_label(misc_ref_invalid) /* 68 even_fixnum  */
3191        .long local_label(misc_ref_invalid) /* 69 cons  */
3192        .long local_label(misc_ref_node) /* 6a slot_vector  */
3193        .long local_label(misc_ref_invalid) /* 6b imm  */
3194        .long local_label(misc_ref_invalid) /* 6c odd_fixnum  */
3195        .long local_label(misc_ref_invalid) /* 6d nil  */
3196        .long local_label(misc_ref_invalid) /* 6e misc  */
3197        .long local_label(misc_ref_invalid) /* 6f immheader  */
3198        /* 70-7*/
3199        .long local_label(misc_ref_invalid) /* 70 even_fixnum  */
3200        .long local_label(misc_ref_invalid) /* 71 cons  */
3201        .long local_label(misc_ref_node) /* 72 instance  */
3202        .long local_label(misc_ref_invalid) /* 73 imm  */
3203        .long local_label(misc_ref_invalid) /* 74 odd_fixnum  */
3204        .long local_label(misc_ref_invalid) /* 75 nil  */
3205        .long local_label(misc_ref_invalid) /* 76 misc  */
3206        .long local_label(misc_ref_invalid) /* 77 immheader  */
3207        .long local_label(misc_ref_invalid) /* 78 even_fixnum  */
3208        .long local_label(misc_ref_invalid) /* 79 cons  */
3209        .long local_label(misc_ref_node) /* 7a struct  */
3210        .long local_label(misc_ref_invalid) /* 7b imm  */
3211        .long local_label(misc_ref_invalid) /* 7c odd_fixnum  */
3212        .long local_label(misc_ref_invalid) /* 7d nil  */
3213        .long local_label(misc_ref_invalid) /* 7e misc  */
3214        .long local_label(misc_ref_invalid) /* 7f immheader  */
3215        /* 80-8*/
3216        .long local_label(misc_ref_invalid) /* 80 even_fixnum  */
3217        .long local_label(misc_ref_invalid) /* 81 cons  */
3218        .long local_label(misc_ref_node) /* 82 istruct  */
3219        .long local_label(misc_ref_invalid) /* 83 imm  */
3220        .long local_label(misc_ref_invalid) /* 84 odd_fixnum  */
3221        .long local_label(misc_ref_invalid) /* 85 nil  */
3222        .long local_label(misc_ref_invalid) /* 86 misc  */
3223        .long local_label(misc_ref_invalid) /* 87 immheader  */
3224        .long local_label(misc_ref_invalid) /* 88 even_fixnum  */
3225        .long local_label(misc_ref_invalid) /* 89 cons  */
3226        .long local_label(misc_ref_node) /* 8a value_cell  */
3227        .long local_label(misc_ref_invalid) /* 8b imm  */
3228        .long local_label(misc_ref_invalid) /* 8c odd_fixnum  */
3229        .long local_label(misc_ref_invalid) /* 8d nil  */
3230        .long local_label(misc_ref_invalid) /* 8e misc  */
3231        .long local_label(misc_ref_invalid) /* 8f immheader  */
3232        /* 90-9*/
3233        .long local_label(misc_ref_invalid) /* 90 even_fixnum  */
3234        .long local_label(misc_ref_invalid) /* 91 cons  */
3235        .long local_label(misc_ref_node) /* 92 xfunction  */
3236        .long local_label(misc_ref_invalid) /* 93 imm  */
3237        .long local_label(misc_ref_invalid) /* 94 odd_fixnum  */
3238        .long local_label(misc_ref_invalid) /* 95 nil  */
3239        .long local_label(misc_ref_invalid) /* 96 misc  */
3240        .long local_label(misc_ref_invalid) /* 97 immheader  */
3241        .long local_label(misc_ref_invalid) /* 98 even_fixnum  */
3242        .long local_label(misc_ref_invalid) /* 99 cons  */
3243        .long local_label(misc_ref_node) /* 9a arrayN  */
3244        .long local_label(misc_ref_invalid) /* 9b imm  */
3245        .long local_label(misc_ref_invalid) /* 9c odd_fixnum  */
3246        .long local_label(misc_ref_invalid) /* 9d nil  */
3247        .long local_label(misc_ref_invalid) /* 9e misc  */
3248        .long local_label(misc_ref_invalid) /* 9f immheader  */
3249        /* a0-af  */
3250        .long local_label(misc_ref_invalid) /* a0 even_fixnum  */
3251        .long local_label(misc_ref_invalid) /* a1 cons  */
3252        .long local_label(misc_ref_node) /* a2 vectorH  */
3253        .long local_label(misc_ref_invalid) /* a3 imm  */
3254        .long local_label(misc_ref_invalid) /* a4 odd_fixnum  */
3255        .long local_label(misc_ref_invalid) /* a5 nil  */
3256        .long local_label(misc_ref_invalid) /* a6 misc  */
3257        .long local_label(misc_ref_single_float_vector) /* a7 sf_vector  */
3258        .long local_label(misc_ref_invalid) /* a8 even_fixnum  */
3259        .long local_label(misc_ref_invalid) /* a9 cons  */
3260        .long local_label(misc_ref_node) /* aa simple_vector  */
3261        .long local_label(misc_ref_invalid) /* ab imm  */
3262        .long local_label(misc_ref_invalid) /* ac odd_fixnum  */
3263        .long local_label(misc_ref_invalid) /* ad nil  */
3264        .long local_label(misc_ref_invalid) /* ae misc  */
3265        .long local_label(misc_ref_u32) /* af u32  */
3266        /* b0-bf  */
3267        .long local_label(misc_ref_invalid) /* b0 even_fixnum  */
3268        .long local_label(misc_ref_invalid) /* b1 cons  */
3269        .long local_label(misc_ref_invalid) /* b2 nodeheader  */
3270        .long local_label(misc_ref_invalid) /* b3 imm  */
3271        .long local_label(misc_ref_invalid) /* b4 odd_fixnum  */
3272        .long local_label(misc_ref_invalid) /* b5 nil  */
3273        .long local_label(misc_ref_invalid) /* b6 misc  */
3274        .long local_label(misc_ref_s32) /* b7 s32  */
3275        .long local_label(misc_ref_invalid) /* b8 even_fixnum  */
3276        .long local_label(misc_ref_invalid) /* b9 cons  */
3277        .long local_label(misc_ref_invalid) /* ba nodeheader  */
3278        .long local_label(misc_ref_invalid) /* bb imm  */
3279        .long local_label(misc_ref_invalid) /* bc odd_fixnum  */
3280        .long local_label(misc_ref_invalid) /* bd nil  */
3281        .long local_label(misc_ref_invalid) /* be misc  */
3282        .long local_label(misc_ref_fixnum_vector) /* bf fixnum_vector  */
3283        /* c0-cf  */
3284        .long local_label(misc_ref_invalid) /* c0 even_fixnum  */
3285        .long local_label(misc_ref_invalid) /* c1 cons  */
3286        .long local_label(misc_ref_invalid) /* c2 nodeheader  */
3287        .long local_label(misc_ref_invalid) /* c3 imm  */
3288        .long local_label(misc_ref_invalid) /* c4 odd_fixnum  */
3289        .long local_label(misc_ref_invalid) /* c5 nil  */
3290        .long local_label(misc_ref_invalid) /* c6 misc  */
3291        .long local_label(misc_ref_new_string) /* c7 new_string  */
3292        .long local_label(misc_ref_invalid) /* c8 even_fixnum  */
3293        .long local_label(misc_ref_invalid) /* c9 cons  */
3294        .long local_label(misc_ref_invalid) /* ca nodeheader  */
3295        .long local_label(misc_ref_invalid) /* cb imm  */
3296        .long local_label(misc_ref_invalid) /* cc odd_fixnum  */
3297        .long local_label(misc_ref_invalid) /* cd nil  */
3298        .long local_label(misc_ref_invalid) /* ce misc  */
3299        .long local_label(misc_ref_u8) /* cf u8  */
3300        /* d0-df  */
3301        .long local_label(misc_ref_invalid) /* d0 even_fixnum  */
3302        .long local_label(misc_ref_invalid) /* d1 cons  */
3303        .long local_label(misc_ref_invalid) /* d2 nodeheader  */
3304        .long local_label(misc_ref_invalid) /* d3 imm  */
3305        .long local_label(misc_ref_invalid) /* d4 odd_fixnum  */
3306        .long local_label(misc_ref_invalid) /* d5 nil  */
3307        .long local_label(misc_ref_invalid) /* d6 misc  */
3308        .long local_label(misc_ref_s8)      /* d7 s8  */
3309        .long local_label(misc_ref_invalid) /* d8 even_fixnum  */
3310        .long local_label(misc_ref_invalid) /* d9 cons  */
3311        .long local_label(misc_ref_invalid) /* da nodeheader  */
3312        .long local_label(misc_ref_invalid) /* db imm  */
3313        .long local_label(misc_ref_invalid) /* dc odd_fixnum  */
3314        .long local_label(misc_ref_invalid) /* dd nil  */
3315        .long local_label(misc_ref_invalid) /* de misc  */
3316        .long local_label(misc_ref_old_string) /* df (old)subtag_simple_base_string  */
3317        /* e0-ef  */
3318        .long local_label(misc_ref_invalid) /* e0 even_fixnum  */
3319        .long local_label(misc_ref_invalid) /* e1 cons  */
3320        .long local_label(misc_ref_invalid) /* e2 nodeheader  */
3321        .long local_label(misc_ref_invalid) /* e3 imm  */
3322        .long local_label(misc_ref_invalid) /* e4 odd_fixnum  */
3323        .long local_label(misc_ref_invalid) /* e5 nil  */
3324        .long local_label(misc_ref_invalid) /* e6 misc  */
3325        .long local_label(misc_ref_u16) /* e7 u16  */
3326        .long local_label(misc_ref_invalid) /* e8 even_fixnum  */
3327        .long local_label(misc_ref_invalid) /* e9 cons  */
3328        .long local_label(misc_ref_invalid) /* ea nodeheader  */
3329        .long local_label(misc_ref_invalid) /* eb imm  */
3330        .long local_label(misc_ref_invalid) /* ec odd_fixnum  */
3331        .long local_label(misc_ref_invalid) /* ed nil  */
3332        .long local_label(misc_ref_invalid) /* ee misc  */
3333        .long local_label(misc_ref_s16) /* ef s16  */
3334        /* f0-ff  */
3335        .long local_label(misc_ref_invalid) /* f0 even_fixnum  */
3336        .long local_label(misc_ref_invalid) /* f1 cons  */
3337        .long local_label(misc_ref_invalid) /* f2 nodeheader  */
3338        .long local_label(misc_ref_invalid) /* f3 imm  */
3339        .long local_label(misc_ref_invalid) /* f4 odd_fixnum  */
3340        .long local_label(misc_ref_invalid) /* f5 nil  */
3341        .long local_label(misc_ref_invalid) /* f6 misc  */
3342        .long local_label(misc_ref_double_float_vector) /* f7 df vector  */
3343        .long local_label(misc_ref_invalid) /* f8 even_fixnum  */
3344        .long local_label(misc_ref_invalid) /* f9 cons  */
3345        .long local_label(misc_ref_invalid) /* fa nodeheader  */
3346        .long local_label(misc_ref_invalid) /* fb imm  */
3347        .long local_label(misc_ref_invalid) /* fc odd_fixnum  */
3348        .long local_label(misc_ref_invalid) /* fd nil  */
3349        .long local_label(misc_ref_invalid) /* fe misc  */
3350        .long local_label(misc_ref_bit_vector) /* ff bit_vector  */
3351
3352local_label(misc_ref_node):       
3353        /* A node vector.  */
3354        __(add imm0,arg_z,#misc_data_offset)
3355        __(ldr  arg_z,[arg_y,imm0])
3356        __(bx lr)
3357local_label(misc_ref_single_float_vector):       
3358        __(add imm0,arg_z,misc_data_offset)
3359        __(movc16(imm1,single_float_header))
3360        __(ldr imm0,[arg_y,imm0])
3361        __(Misc_Alloc_Fixed(arg_z,imm1,single_float.size))
3362        __(str imm0,[arg_z,#single_float.value])
3363        __(bx lr)
3364local_label(misc_ref_new_string):       
3365        __(add imm0,arg_z,#misc_data_offset)
3366        __(ldr imm0,[arg_y,imm0])
3367        __(mov arg_z,imm0,lsl #charcode_shift)
3368        __(orr arg_z,arg_z,#subtag_character)
3369        __(bx lr)
3370local_label(misc_ref_s32):       
3371        __(add imm0,arg_z,#misc_data_offset)
3372        __(ldr imm0,[arg_y,imm0])
3373        __(b _SPmakes32)
3374local_label(misc_ref_fixnum_vector):   
3375        __(add imm0,arg_z,#misc_data_offset)
3376        __(ldr imm0,[arg_y,imm0])
3377        __(box_fixnum(arg_z,imm0))
3378        __(bx lr)       
3379local_label(misc_ref_u32):       
3380        __(add imm0,arg_z,#misc_data_offset)
3381        __(ldr imm0,[arg_y,imm0])
3382        __(b _SPmakeu32)
3383local_label(misc_ref_double_float_vector):     
3384        __(mov imm0,arg_z,lsl #1)
3385        __(add imm0,imm0,#misc_dfloat_offset)
3386        __(ldrd imm0,imm1,[arg_y,imm0])
3387        __(movc16(imm2,double_float_header))
3388        __(Misc_Alloc_Fixed(arg_z,imm2,double_float.size))
3389        __(strd imm0,imm1,[arg_z,#double_float.value])
3390        __(bx lr)
3391local_label(misc_ref_bit_vector):
3392        __(mov imm1,#nbits_in_word-1)
3393        __(and imm1,imm1,arg_z,lsr #2)
3394        __(mov imm2,#1)
3395        __(mov imm2,imm2,lsl imm1)
3396        __(mov imm0,arg_z,lsr #5+fixnumshift)
3397        __(mov imm0,imm0,lsl #2)
3398        __(add imm0,imm0,#misc_data_offset)
3399        __(mov arg_z,#0)
3400        __(ldr imm0,[arg_y,imm0])
3401        __(tst imm0,imm2)
3402        __(addne arg_z,arg_z,#fixnumone)
3403        __(bx lr)
3404local_label(misc_ref_s8):       
3405        __(mov imm0,arg_z,lsr #2)
3406        __(add imm0,imm0,#misc_data_offset)
3407        __(ldsb imm0,[arg_y,imm0])
3408        __(box_fixnum(arg_z,imm0))
3409        __(bx lr)
3410local_label(misc_ref_u8):       
3411        __(mov imm0,arg_z,lsr #2)
3412        __(add imm0,imm0,#misc_data_offset)
3413        __(ldrb imm0,[arg_y,imm0])
3414        __(box_fixnum(arg_z,imm0))
3415        __(bx lr)
3416local_label(misc_ref_old_string):         
3417        __(mov imm0,arg_z,lsr #2)
3418        __(add imm0,imm0,#misc_data_offset)
3419        __(ldrb imm0,[arg_y,imm0])
3420        __(mov arg_z,imm0,lsl #charcode_shift)
3421        __(orr arg_z,arg_z,#subtag_character)
3422        __(bx lr)
3423local_label(misc_ref_u16):       
3424        __(mov imm0,arg_z,lsr #1)     
3425        __(add imm0,imm0,#misc_data_offset)
3426        __(ldrh imm0,[arg_y,imm0])
3427        __(box_fixnum(arg_z,imm0))
3428        __(bx lr)
3429local_label(misc_ref_s16):             
3430        __(mov imm0,arg_z,lsr #1)     
3431        __(add imm0,imm0,#misc_data_offset)
3432        __(ldrsh imm0,[arg_y,imm0])
3433        __(box_fixnum(arg_z,imm0))
3434        __(bx lr)
3435local_label(misc_ref_invalid):
3436        __(mov arg_x,#XBADVEC)
3437        __(set_nargs(3))
3438        __(b _SPksignalerr)       
3439_endfn
3440       
3441_exportfn(C(misc_set_common))
3442        __(adr imm0,local_label(misc_set_jmp))
3443        __(ldr pc,[imm0,imm1,lsl #2])
3444local_label(misc_set_jmp):             
3445        /* 00-0*/
3446        .long local_label(misc_set_invalid) /* 00 even_fixnum  */
3447        .long local_label(misc_set_invalid) /* 01 cons  */
3448        .long local_label(misc_set_invalid) /* 02 nodeheader  */
3449        .long local_label(misc_set_invalid) /* 03 imm  */
3450        .long local_label(misc_set_invalid) /* 04 odd_fixnum  */
3451        .long local_label(misc_set_invalid) /* 05 nil  */
3452        .long local_label(misc_set_invalid) /* 06 misc  */
3453        .long local_label(misc_set_u32) /* 07 bignum  */
3454        .long local_label(misc_set_invalid) /* 08 even_fixnum  */
3455        .long local_label(misc_set_invalid) /* 09 cons  */
3456        .long _SPgvset /* 0a ratio  */
3457        .long local_label(misc_set_invalid) /* 0b imm  */
3458        .long local_label(misc_set_invalid) /* 0c odd_fixnum  */
3459        .long local_label(misc_set_invalid) /* 0d nil  */
3460        .long local_label(misc_set_invalid) /* 0e misc  */
3461        .long local_label(misc_set_u32) /* 0f single_float  */
3462        /* 10-1*/
3463        .long local_label(misc_set_invalid) /* 10 even_fixnum  */
3464        .long local_label(misc_set_invalid) /* 11 cons  */
3465        .long local_label(misc_set_invalid) /* 12 nodeheader  */
3466        .long local_label(misc_set_invalid) /* 13 imm  */
3467        .long local_label(misc_set_invalid) /* 14 odd_fixnum  */
3468        .long local_label(misc_set_invalid) /* 15 nil  */
3469        .long local_label(misc_set_invalid) /* 16 misc  */
3470        .long local_label(misc_set_u32) /* 17 double_float  */
3471        .long local_label(misc_set_invalid) /* 18 even_fixnum  */
3472        .long local_label(misc_set_invalid) /* 19 cons  */
3473        .long _SPgvset /* 1a complex  */
3474        .long local_label(misc_set_invalid) /* 1b imm  */
3475        .long local_label(misc_set_invalid) /* 1c odd_fixnum  */
3476        .long local_label(misc_set_invalid) /* 1d nil  */
3477        .long local_label(misc_set_invalid) /* 1e misc  */
3478        .long local_label(misc_set_u32) /* 1f macptr  */
3479        /* 20-2*/
3480        .long local_label(misc_set_invalid) /* 20 even_fixnum  */
3481        .long local_label(misc_set_invalid) /* 21 cons  */
3482        .long _SPgvset /* 22 catch_frame  */
3483        .long local_label(misc_set_invalid) /* 23 imm  */
3484        .long local_label(misc_set_invalid) /* 24 odd_fixnum  */
3485        .long local_label(misc_set_invalid) /* 25 nil  */
3486        .long local_label(misc_set_invalid) /* 26 misc  */
3487        .long local_label(misc_set_u32) /* 27 dead_macptr  */
3488        .long local_label(misc_set_invalid) /* 28 even_fixnum  */
3489        .long local_label(misc_set_invalid) /* 29 cons  */
3490        .long _SPgvset /* 2a function  */
3491        .long local_label(misc_set_invalid) /* 2b imm  */
3492        .long local_label(misc_set_invalid) /* 2c odd_fixnum  */
3493        .long local_label(misc_set_invalid) /* 2d nil  */
3494        .long local_label(misc_set_invalid) /* 2e misc  */
3495        .long local_label(misc_set_u32) /* 2f code_vector  */
3496        /* 30-3*/
3497        .long local_label(misc_set_invalid) /* 30 even_fixnum  */
3498        .long local_label(misc_set_invalid) /* 31 cons  */
3499        .long _SPgvset /* 32 lisp_thread  */
3500        .long local_label(misc_set_invalid) /* 33 imm  */
3501        .long local_label(misc_set_invalid) /* 34 odd_fixnum  */
3502        .long local_label(misc_set_invalid) /* 35 nil  */
3503        .long local_label(misc_set_invalid) /* 36 misc  */
3504        .long local_label(misc_set_u32) /* 37 creole  */
3505        .long local_label(misc_set_invalid) /* 38 even_fixnum  */
3506        .long local_label(misc_set_invalid) /* 39 cons  */
3507        .long _SPgvset /* 3a symbol  */
3508        .long local_label(misc_set_invalid) /* 3b imm  */
3509        .long local_label(misc_set_invalid) /* 3c odd_fixnum  */
3510        .long local_label(misc_set_invalid) /* 3d nil  */
3511        .long local_label(misc_set_invalid) /* 3e misc  */
3512        .long local_label(misc_set_u32) /* 3f xcode_vector  */
3513        /* 40-4*/
3514        .long local_label(misc_set_invalid) /* 40 even_fixnum  */
3515        .long local_label(misc_set_invalid) /* 41 cons  */
3516        .long _SPgvset /* 42 lock  */
3517        .long local_label(misc_set_invalid) /* 43 imm  */
3518        .long local_label(misc_set_invalid) /* 44 odd_fixnum  */
3519        .long local_label(misc_set_invalid) /* 45 nil  */
3520        .long local_label(misc_set_invalid) /* 46 misc  */
3521        .long local_label(misc_set_invalid) /* 47 immheader  */
3522        .long local_label(misc_set_invalid) /* 48 even_fixnum  */
3523        .long local_label(misc_set_invalid) /* 49 cons  */
3524        .long _SPgvset /* 4a hash_vector  */
3525        .long local_label(misc_set_invalid) /* 4b imm  */
3526        .long local_label(misc_set_invalid) /* 4c odd_fixnum  */
3527        .long local_label(misc_set_invalid) /* 4d nil  */
3528        .long local_label(misc_set_invalid) /* 4e misc  */
3529        .long local_label(misc_set_invalid) /* 4f immheader  */
3530        /* 50-5*/
3531        .long local_label(misc_set_invalid) /* 50 even_fixnum  */
3532        .long local_label(misc_set_invalid) /* 51 cons  */
3533        .long _SPgvset /* 52 pool  */
3534        .long local_label(misc_set_invalid) /* 53 imm  */
3535        .long local_label(misc_set_invalid) /* 54 odd_fixnum  */
3536        .long local_label(misc_set_invalid) /* 55 nil  */
3537        .long local_label(misc_set_invalid) /* 56 misc  */
3538        .long local_label(misc_set_invalid) /* 57 immheader  */
3539        .long local_label(misc_set_invalid) /* 58 even_fixnum  */
3540        .long local_label(misc_set_invalid) /* 59 cons  */
3541        .long _SPgvset /* 5a weak  */
3542        .long local_label(misc_set_invalid) /* 5b imm  */
3543        .long local_label(misc_set_invalid) /* 5c odd_fixnum  */
3544        .long local_label(misc_set_invalid) /* 5d nil  */
3545        .long local_label(misc_set_invalid) /* 5e misc  */
3546        .long local_label(misc_set_invalid) /* 5f immheader  */
3547        /* 60-6*/
3548        .long local_label(misc_set_invalid) /* 60 even_fixnum  */
3549        .long local_label(misc_set_invalid) /* 61 cons  */
3550        .long _SPgvset /* 62 package  */
3551        .long local_label(misc_set_invalid) /* 63 imm  */
3552        .long local_label(misc_set_invalid) /* 64 odd_fixnum  */
3553        .long local_label(misc_set_invalid) /* 65 nil  */
3554        .long local_label(misc_set_invalid) /* 66 misc  */
3555        .long local_label(misc_set_invalid) /* 67 immheader  */
3556        .long local_label(misc_set_invalid) /* 68 even_fixnum  */
3557        .long local_label(misc_set_invalid) /* 69 cons  */
3558        .long _SPgvset /* 6a slot_vector  */
3559        .long local_label(misc_set_invalid) /* 6b imm  */
3560        .long local_label(misc_set_invalid) /* 6c odd_fixnum  */
3561        .long local_label(misc_set_invalid) /* 6d nil  */
3562        .long local_label(misc_set_invalid) /* 6e misc  */
3563        .long local_label(misc_set_invalid) /* 6f immheader  */
3564        /* 70-7*/
3565        .long local_label(misc_set_invalid) /* 70 even_fixnum  */
3566        .long local_label(misc_set_invalid) /* 71 cons  */
3567        .long _SPgvset /* 72 instance  */
3568        .long local_label(misc_set_invalid) /* 73 imm  */
3569        .long local_label(misc_set_invalid) /* 74 odd_fixnum  */
3570        .long local_label(misc_set_invalid) /* 75 nil  */
3571        .long local_label(misc_set_invalid) /* 76 misc  */
3572        .long local_label(misc_set_invalid) /* 77 immheader  */
3573        .long local_label(misc_set_invalid) /* 78 even_fixnum  */
3574        .long local_label(misc_set_invalid) /* 79 cons  */
3575        .long _SPgvset /* 7a struct  */
3576        .long local_label(misc_set_invalid) /* 7b imm  */
3577        .long local_label(misc_set_invalid) /* 7c odd_fixnum  */
3578        .long local_label(misc_set_invalid) /* 7d nil  */
3579        .long local_label(misc_set_invalid) /* 7e misc  */
3580        .long local_label(misc_set_invalid) /* 7f immheader  */
3581        /* 80-8*/
3582        .long local_label(misc_set_invalid) /* 80 even_fixnum  */
3583        .long local_label(misc_set_invalid) /* 81 cons  */
3584        .long _SPgvset /* 82 istruct  */
3585        .long local_label(misc_set_invalid) /* 83 imm  */
3586        .long local_label(misc_set_invalid) /* 84 odd_fixnum  */
3587        .long local_label(misc_set_invalid) /* 85 nil  */
3588        .long local_label(misc_set_invalid) /* 86 misc  */
3589        .long local_label(misc_set_invalid) /* 87 immheader  */
3590        .long local_label(misc_set_invalid) /* 88 even_fixnum  */
3591        .long local_label(misc_set_invalid) /* 89 cons  */
3592        .long _SPgvset /* 8a value_cell  */
3593        .long local_label(misc_set_invalid) /* 8b imm  */
3594        .long local_label(misc_set_invalid) /* 8c odd_fixnum  */
3595        .long local_label(misc_set_invalid) /* 8d nil  */
3596        .long local_label(misc_set_invalid) /* 8e misc  */
3597        .long local_label(misc_set_invalid) /* 8f immheader  */
3598        /* 90-9*/
3599        .long local_label(misc_set_invalid) /* 90 even_fixnum  */
3600        .long local_label(misc_set_invalid) /* 91 cons  */
3601        .long _SPgvset /* 92 xfunction  */
3602        .long local_label(misc_set_invalid) /* 93 imm  */
3603        .long local_label(misc_set_invalid) /* 94 odd_fixnum  */
3604        .long local_label(misc_set_invalid) /* 95 nil  */
3605        .long local_label(misc_set_invalid) /* 96 misc  */
3606        .long local_label(misc_set_invalid) /* 97 immheader  */
3607        .long local_label(misc_set_invalid) /* 98 even_fixnum  */
3608        .long local_label(misc_set_invalid) /* 99 cons  */
3609        .long _SPgvset /* 9a arrayH  */
3610        .long local_label(misc_set_invalid) /* 9b imm  */
3611        .long local_label(misc_set_invalid) /* 9c odd_fixnum  */
3612        .long local_label(misc_set_invalid) /* 9d nil  */
3613        .long local_label(misc_set_invalid) /* 9e misc  */
3614        .long local_label(misc_set_invalid) /* 9f immheader  */
3615        /* a0-af  */
3616        .long local_label(misc_set_invalid) /* a0 even_fixnum  */
3617        .long local_label(misc_set_invalid) /* a1 cons  */
3618        .long _SPgvset /* a2 vectorH  */
3619        .long local_label(misc_set_invalid) /* a3 imm  */
3620        .long local_label(misc_set_invalid) /* a4 odd_fixnum  */
3621        .long local_label(misc_set_invalid) /* a5 nil  */
3622        .long local_label(misc_set_invalid) /* a6 misc  */
3623        .long local_label(misc_set_single_float_vector) /* a7 sf vector  */
3624        .long local_label(misc_set_invalid) /* a8 even_fixnum  */
3625        .long local_label(misc_set_invalid) /* a9 cons  */
3626        .long _SPgvset /* aa vectorH  */
3627        .long local_label(misc_set_invalid) /* ab imm  */
3628        .long local_label(misc_set_invalid) /* ac odd_fixnum  */
3629        .long local_label(misc_set_invalid) /* ad nil  */
3630        .long local_label(misc_set_invalid) /* ae misc  */
3631        .long local_label(misc_set_u32) /* af u32  */
3632        /* b0-bf  */
3633        .long local_label(misc_set_invalid) /* b0 even_fixnum  */
3634        .long local_label(misc_set_invalid) /* b1 cons  */
3635        .long local_label(misc_set_invalid) /* b2 node  */
3636        .long local_label(misc_set_invalid) /* b3 imm  */
3637        .long local_label(misc_set_invalid) /* b4 odd_fixnum  */
3638        .long local_label(misc_set_invalid) /* b5 nil  */
3639        .long local_label(misc_set_invalid) /* b6 misc  */
3640        .long local_label(misc_set_s32) /* b7 s32  */
3641        .long local_label(misc_set_invalid) /* b8 even_fixnum  */
3642        .long local_label(misc_set_invalid) /* b9 cons  */
3643        .long local_label(misc_set_invalid) /* ba nodeheader  */
3644        .long local_label(misc_set_invalid) /* bb imm  */
3645        .long local_label(misc_set_invalid) /* bc odd_fixnum  */
3646        .long local_label(misc_set_invalid) /* bd nil  */
3647        .long local_label(misc_set_invalid) /* be misc  */
3648        .long local_label(misc_set_fixnum_vector) /* bf fixnum_vector  */
3649        /* c0-cf  */
3650        .long local_label(misc_set_invalid) /* c0 even_fixnum  */
3651        .long local_label(misc_set_invalid) /* c1 cons  */
3652        .long local_label(misc_set_invalid) /* c2 nodeheader  */
3653        .long local_label(misc_set_invalid) /* c3 imm  */
3654        .long local_label(misc_set_invalid) /* c4 odd_fixnum  */
3655        .long local_label(misc_set_invalid) /* c5 nil  */
3656        .long local_label(misc_set_invalid) /* c6 misc  */
3657        .long local_label(misc_set_new_string) /* c7 new_string  */
3658        .long local_label(misc_set_invalid) /* c8 even_fixnum  */
3659        .long local_label(misc_set_invalid) /* c9 cons  */
3660        .long local_label(misc_set_invalid) /* ca nodeheader  */
3661        .long local_label(misc_set_invalid) /* cb imm  */
3662        .long local_label(misc_set_invalid) /* cc odd_fixnum  */
3663        .long local_label(misc_set_invalid) /* cd nil  */
3664        .long local_label(misc_set_invalid) /* ce misc  */
3665        .long local_label(misc_set_u8) /* cf u8  */
3666        /* d0-df  */
3667        .long local_label(misc_set_invalid) /* d0 even_fixnum  */
3668        .long local_label(misc_set_invalid) /* d1 cons  */
3669        .long local_label(misc_set_invalid) /* d2 nodeheader  */
3670        .long local_label(misc_set_invalid) /* d3 imm  */
3671        .long local_label(misc_set_invalid) /* d4 odd_fixnum  */
3672        .long local_label(misc_set_invalid) /* d5 nil  */
3673        .long local_label(misc_set_invalid) /* d6 misc  */
3674        .long local_label(misc_set_s8) /* d7 s8  */
3675        .long local_label(misc_set_invalid) /* d8 even_fixnum  */
3676        .long local_label(misc_set_invalid) /* d9 cons  */
3677        .long local_label(misc_set_invalid) /* da nodeheader  */
3678        .long local_label(misc_set_invalid) /* db imm  */
3679        .long local_label(misc_set_invalid) /* dc odd_fixnum  */
3680        .long local_label(misc_set_invalid) /* dd nil  */
3681        .long local_label(misc_set_invalid) /* de misc  */
3682        .long local_label(misc_set_old_string) /* df (old) simple_base_string  */
3683        /* e0-ef  */
3684        .long local_label(misc_set_invalid) /* e0 even_fixnum  */
3685        .long local_label(misc_set_invalid) /* e1 cons  */
3686        .long local_label(misc_set_invalid) /* e2 nodeheader  */
3687        .long local_label(misc_set_invalid) /* e3 imm  */
3688        .long local_label(misc_set_invalid) /* e4 odd_fixnum  */
3689        .long local_label(misc_set_invalid) /* e5 nil  */
3690        .long local_label(misc_set_invalid) /* e6 misc  */
3691        .long local_label(misc_set_u16) /* e7 u16  */
3692        .long local_label(misc_set_invalid) /* e8 even_fixnum  */
3693        .long local_label(misc_set_invalid) /* e9 cons  */
3694        .long local_label(misc_set_invalid) /* ea nodeheader  */
3695        .long local_label(misc_set_invalid) /* eb imm  */
3696        .long local_label(misc_set_invalid) /* ec odd_fixnum  */
3697        .long local_label(misc_set_invalid) /* ed nil  */
3698        .long local_label(misc_set_invalid) /* ee misc  */
3699        .long local_label(misc_set_s16) /* ef s16  */
3700        /* f0-ff  */
3701        .long local_label(misc_set_invalid) /* f0 even_fixnum  */
3702        .long local_label(misc_set_invalid) /* f1 cons  */
3703        .long local_label(misc_set_invalid) /* f2 nodeheader  */
3704        .long local_label(misc_set_invalid) /* f3 imm  */
3705        .long local_label(misc_set_invalid) /* f4 odd_fixnum  */
3706        .long local_label(misc_set_invalid) /* f5 nil  */
3707        .long local_label(misc_set_invalid) /* f6 misc  */
3708        .long local_label(misc_set_double_float_vector) /* f7 df vector  */
3709        .long local_label(misc_set_invalid) /* f8 even_fixnum  */
3710        .long local_label(misc_set_invalid) /* f9 cons  */
3711        .long local_label(misc_set_invalid) /* fa nodeheader  */
3712        .long local_label(misc_set_invalid) /* fb imm  */
3713        .long local_label(misc_set_invalid) /* fc odd_fixnum  */
3714        .long local_label(misc_set_invalid) /* fd nil  */
3715        .long local_label(misc_set_invalid) /* fe misc  */
3716        .long local_label(misc_set_bit_vector) /* ff bit_vector  */
3717
3718local_label(misc_set_u32):       
3719        /* Either a non-negative fixnum, a positive one-digit bignum, */
3720        /* or a two-digit bignum whose sign-digit is 0 is ok.  */
3721        __(add imm0,arg_y,#misc_data_offset)
3722        __(test_fixnum(arg_z))
3723        __(bne local_label(set_not_fixnum_u32))
3724        __(tst arg_z,#0x80000000)
3725        __(bne local_label(set_bad))
3726        __(unbox_fixnum(imm1,arg_z))
3727local_label(set_set32):         
3728        __(str imm1,[arg_x,imm0])
3729        __(bx lr)
3730local_label(set_not_fixnum_u32):
3731        __(extract_lisptag(imm1,arg_z))
3732        __(cmp imm1,#tag_misc)
3733        __(bne local_label(set_bad))
3734        __(movc16(imm2,one_digit_bignum_header))
3735        __(getvheader(imm1,arg_z))
3736        __(cmp imm1,imm2)
3737        __(bne local_label(set_not_1_digit_u32))
3738        __(ldr imm1,[arg_z,#misc_data_offset])
3739        __(cmp imm1,#0)
3740        __(bge local_label(set_set32))
3741        __(b local_label(set_bad))
3742local_label(set_not_1_digit_u32):
3743        __(movc16(imm2,two_digit_bignum_header))
3744        __(cmp imm1,imm2)
3745        __(bne local_label(set_bad))
3746        __(vrefr(imm2,arg_z,1))
3747        __(vrefr(imm1,arg_z,0))
3748        __(cmp imm2,#0)
3749        __(beq local_label(set_set32))
3750local_label(set_bad):
3751        /* arg_z does not match the array-element-type of arg_x.  */
3752        __(mov arg_y,arg_z)
3753        __(mov arg_z,arg_x)
3754        __(mov arg_x,#XNOTELT)
3755        __(set_nargs(3))
3756        __(b _SPksignalerr)
3757local_label(misc_set_fixnum_vector):   
3758        __(add imm0,arg_y,#misc_data_offset)
3759        __(test_fixnum(arg_z))
3760        __(bne local_label(set_bad))
3761        __(unbox_fixnum(imm1,arg_z))
3762        __(str imm1,[arg_x,imm0])
3763        __(bx lr)
3764local_label(misc_set_new_string):   
3765        __(add imm0,arg_y,#misc_data_offset)
3766        __(extract_lowbyte(imm2,arg_z))
3767        __(cmp imm2,#subtag_character)
3768        __(bne local_label(set_bad))
3769        __(unbox_character(imm1,arg_z))
3770        __(str imm1,[arg_x,imm0])
3771        __(bx lr)
3772local_label(misc_set_s32):
3773        __(add imm0,arg_y,#misc_data_offset)
3774        __(test_fixnum(arg_z))
3775        __(moveq imm1,arg_z,asr #fixnumshift)
3776        __(beq local_label(set_set32))
3777        __(extract_lisptag(imm2,arg_z))
3778        __(cmp imm2,#tag_misc)
3779        __(bne local_label(set_bad))
3780        __(movc16(imm1,one_digit_bignum_header))
3781        __(getvheader(imm2,arg_z))
3782        __(cmp imm2,imm1)
3783        __(vrefr(imm1,arg_z,0))
3784        __(beq local_label(set_set32))
3785        __(b local_label(set_bad))
3786local_label(misc_set_single_float_vector):
3787        __(add imm0,arg_y,#misc_data_offset)
3788        __(extract_typecode(imm2,arg_z))
3789        __(cmp imm2,#subtag_single_float)
3790        __(bne local_label(set_bad))
3791        __(ldr imm1,[arg_z,#single_float.value])
3792        __(str imm1,[arg_x,imm0])
3793        __(bx lr)
3794local_label(misc_set_u8):               
3795        __(mov imm0,arg_y,lsr #2)
3796        __(add imm0,imm0,#misc_data_offset)
3797        __(mov imm2,#~(0xff<<fixnumshift))
3798        __(tst arg_z,imm2)
3799        __(bne local_label(set_bad))
3800        __(unbox_fixnum(imm1,arg_z))
3801        __(strb imm1,[arg_x,imm0])
3802        __(bx lr)
3803local_label(misc_set_old_string):
3804        __(mov imm0,arg_y,lsr #2)
3805        __(add imm0,imm0,#misc_data_offset)
3806        __(extract_lowbyte(imm2,arg_z))
3807        __(cmp imm2,#subtag_character)
3808        __(unbox_character(imm1,arg_z))
3809        __(bne local_label(set_bad))
3810        __(strb imm1,[arg_x,imm0])
3811        __(bx lr)
3812local_label(misc_set_s8):
3813        __(mov imm0,arg_y,lsr #2)
3814        __(add imm0,imm0,#misc_data_offset)
3815        __(test_fixnum(arg_z))
3816        __(bne local_label(set_bad))
3817        __(unbox_fixnum(imm1,arg_z))
3818        __(mov imm2,imm1,lsl #32-8)
3819        __(cmp imm1,imm2,asr #32-8)
3820        __(bne local_label(set_bad))
3821        __(strb imm1,[arg_x,imm0])
3822        __(bx lr)
3823local_label(misc_set_u16):         
3824        __(mov imm0,arg_y,lsr #1)
3825        __(add imm0,imm0,#misc_data_offset)
3826        __(test_fixnum(arg_z))
3827        __(bne local_label(set_bad))
3828        __(unbox_fixnum(imm1,arg_z))
3829        __(mov imm2,imm1,lsl #16)
3830        __(cmp imm1,imm2,lsr #16)
3831        __(bne local_label(set_bad))
3832        __(strh imm1,[arg_x,imm0])
3833        __(bx lr)
3834local_label(misc_set_s16):
3835        __(mov imm0,arg_y,lsr #1)
3836        __(add imm0,imm0,#misc_data_offset)
3837        __(test_fixnum(arg_z))
3838        __(bne local_label(set_bad))
3839        __(unbox_fixnum(imm1,arg_z))
3840        __(mov imm2,imm1,lsl #16)
3841        __(cmp imm1,imm2,asr #16)
3842        __(bne local_label(set_bad))
3843        __(strh imm1,[arg_x,imm0])
3844        __(bx lr)
3845local_label(misc_set_bit_vector):
3846        __(bics imm0,arg_z,#fixnumone)
3847        __(bne local_label(set_bad))
3848        __(mov imm2,#31)
3849        __(and imm2,imm2,arg_y,lsr #2)
3850        __(mov imm1,#1)
3851        __(mov imm1,imm1,lsl imm2)
3852        __(mov imm0,arg_y,lsr #fixnumshift+5)
3853        __(mov imm0,imm0,lsl #2)
3854        __(add imm0,imm0,#misc_data_offset)
3855        __(cmp arg_z,#0)
3856        __(ldr imm2,[arg_x,imm0])
3857        __(orrne imm2,imm2,imm1)
3858        __(biceq imm2,imm2,imm1)
3859        __(str imm2,[arg_x,imm0])
3860        __(bx lr)
3861
3862local_label(misc_set_double_float_vector):
3863        __(extract_subtag(imm2,arg_z))
3864        __(cmp imm2,#subtag_double_float)
3865        __(bne local_label(set_bad))
3866        __(ldrd imm0,imm1,[arg_z,#misc_dfloat_offset])
3867        __(mov imm2,arg_y,lsl #1)
3868        __(add imm2,imm2,#misc_dfloat_offset)
3869        __(strd imm0,imm1,[arg_x,imm2])
3870        __(bx lr)
3871local_label(misc_set_invalid): 
3872        __(mov temp0,#XSETBADVEC)       
3873        __(set_nargs(4))
3874        __(vpush1(temp0))
3875        __(b _SPksignalerr)               
3876
3877       
3878/* temp0: (stack-consed) target catch frame, imm0: count of intervening  */
3879/* frames. If target isn't a multiple-value receiver, discard extra values */
3880/* (less hair, maybe.)  */
3881_exportfn(C(_throw_found))
3882        new_local_labels()
3883        __(ldr imm1,[temp0,#catch_frame.mvflag])
3884        __(cmp imm1,#0)
3885        __(mov fn,#0)
3886        __(add imm1,vsp,nargs)
3887        __(add imm1,imm1,#-node_size)
3888        __(bne local_label(throw_all_values))
3889        __(cmp nargs,#0)
3890        __(moveq imm1,#nil_value)
3891        __(set_nargs(1))
3892        __(streq imm1,[vsp,#-node_size]!)
3893        __(movne vsp,imm1)
3894local_label(throw_all_values): 
3895        __(bl _SPnthrowvalues)
3896        __(ldr temp0,[rcontext,#tcr.catch_top])
3897        __(ldr imm1,[rcontext,#tcr.db_link])
3898        __(ldr imm0,[temp0,#catch_frame.db_link])
3899        __(cmp imm0,imm1)
3900        __(blne _SPunbind_to)
3901        __(ldr temp1,[temp0,#catch_frame.mvflag])
3902        __(ldr imm0,[temp0,#catch_frame.xframe])       
3903        __(ldr imm1,[temp0,#catch_frame.last_lisp_frame])
3904        __(cmp temp1,#0)
3905        __(str imm0,[rcontext,#tcr.xframe])
3906        __(str imm1,[rcontext,#tcr.last_lisp_frame])
3907        __(add imm0,vsp,nargs)
3908        __(sub sp,temp0,#fulltag_misc)
3909        __(ldr imm1,[sp,#catch_frame.size+lisp_frame.savevsp])
3910        __(ldreq arg_z,[imm0,#-node_size])
3911        __(beq local_label(throw_pushed_values))
3912        __(movs arg_x,nargs)
3913        __(b local_label(throw_push_test))
3914local_label(throw_push_loop):
3915        __(subs arg_x,arg_x,#fixnumone)
3916        __(ldr arg_y,[imm0,#-node_size]!)
3917        __(push1(arg_y,imm1))
3918local_label(throw_push_test):   
3919        __(bne local_label(throw_push_loop))
3920local_label(throw_pushed_values):
3921        __(mov vsp,imm1)
3922        __(ldr imm0,[temp0,#catch_frame.link])
3923        __(str imm0,[rcontext,#tcr.catch_top])
3924        __(ldr fn,[sp,#catch_frame.size+lisp_frame.savefn])
3925        __(ldr lr,[sp,#catch_frame.size+lisp_frame.savelr])
3926        __(add sp,sp,#catch_frame.size+lisp_frame.size)
3927        __(bx lr)
3928_endfn(C(_throw_found))       
3929
3930_exportfn(C(nthrow1v))
3931        new_local_labels()
3932local_label(_nthrow1v_nextframe):
3933        __(subs temp2,temp2,#fixnum_one)
3934        __(ldr temp0,[rcontext,#tcr.catch_top])
3935        __(ldr imm1,[rcontext,#tcr.db_link])
3936        __(set_nargs(1))
3937        __(blt local_label(_nthrow1v_done))
3938        __(ldr arg_y,[temp0,#catch_frame.link])
3939        __(ldr imm0,[temp0,#catch_frame.db_link])
3940        __(cmp imm0,imm1)
3941        __(str arg_y,[rcontext,#tcr.catch_top])
3942        __(ldr arg_y,[temp0,#catch_frame.xframe])
3943        __(str arg_y,[rcontext,#tcr.xframe])
3944        __(beq local_label(_nthrow1v_dont_unbind))
3945        __(do_unbind_to(imm1,temp1,arg_x,arg_y))
3946local_label(_nthrow1v_dont_unbind):
3947        __(ldr temp1,[temp0,#catch_frame.catch_tag])
3948        __(cmp temp1,#unbound_marker)  /* unwind-protect ?  */
3949        __(sub sp,temp0,#fulltag_misc)
3950        __(beq local_label(_nthrow1v_do_unwind))
3951        /* A catch frame.  If the last one, restore context from there.  */
3952        __(cmp temp2,#0)
3953        __(ldreq vsp,[sp,#catch_frame.size+lisp_frame.savevsp])
3954        __(add sp,sp,#catch_frame.size+lisp_frame.size)
3955        __(b local_label(_nthrow1v_nextframe))
3956local_label(_nthrow1v_do_unwind):
3957        /* This is harder, but not as hard (not as much BLTing) as the  */
3958        /* multiple-value case.  */
3959        /* Save our caller's LR and FN in the csp frame created by the unwind-  */
3960        /* protect.  (Clever, eh ?)  */
3961        __(add sp,sp,#catch_frame.size)
3962        /* swp is deprecated on ARMv6+.  It's not useful as a basis
3963           for synchronization, but that's not why we're using it here. */
3964        __(mov imm1,#0)
3965        __(mov temp0,sp)
3966        __(mov imm0,#3<<num_subtag_bits)
3967        __(orr imm0,imm0,#subtag_simple_vector)
3968        __(stmdb sp!,{imm0,imm1,arg_z,temp2})
3969        __(add imm0,temp0,#lisp_frame.savelr)
3970        __(swp lr,lr,[imm0])
3971        __(ldr nfn,[temp0,#lisp_frame.savefn])
3972        __(str fn,[temp0,#lisp_frame.savefn])
3973        __(ldr vsp,[temp0,#lisp_frame.savevsp])
3974        __(mov fn,nfn)
3975        __(str imm1,[rcontext,#tcr.unwinding])
3976        __(blx lr)
3977        __(mov imm1,#1)
3978        __(ldr arg_z,[sp,#8])
3979        __(str imm1,[rcontext,#tcr.unwinding])
3980        __(ldr temp2,[sp,#12])
3981        __(add sp,sp,#4*node_size)
3982        __(restore_lisp_frame(imm0))
3983        __(b local_label(_nthrow1v_nextframe))
3984local_label(_nthrow1v_done):
3985        __(mov imm0,#0)
3986        __(str imm0,[rcontext,#tcr.unwinding])
3987        /* nargs has an undefined value here, so we can clobber it while */
3988        /* polling for a deferred interrupt  */
3989        __(check_pending_interrupt(nargs))
3990        __(bx lr)
3991_endfn       
3992
3993_exportfn(C(nthrownv))
3994        new_local_labels()
3995local_label(nthrownv_nextframe):
3996        __(subs temp2,temp2,#fixnum_one)
3997        __(ldr temp0,[rcontext,#tcr.catch_top])
3998        __(ldr imm1,[rcontext,#tcr.db_link])
3999        __(blt local_label(nthrownv_done))
4000        __(ldr arg_y,[temp0,#catch_frame.link])
4001        __(ldr imm0,[temp0,#catch_frame.db_link])
4002        __(cmp imm0,imm1)
4003        __(str arg_y,[rcontext,#tcr.catch_top])
4004        __(ldr arg_y,[temp0,#catch_frame.xframe])
4005        __(str arg_y,[rcontext,#tcr.xframe])
4006        __(beq local_label(nthrownv_dont_unbind))
4007        __(do_unbind_to(imm1,temp1,arg_x,arg_y))
4008local_label(nthrownv_dont_unbind):
4009        __(ldr temp1,[temp0,#catch_frame.catch_tag])
4010        __(cmp temp1,#unbound_marker)  /* unwind-protect ?  */
4011        __(sub sp,temp0,#fulltag_misc)
4012        __(beq local_label(nthrownv_do_unwind))
4013        __(cmp temp2,#0)
4014/* A catch frame.  If the last one, restore context from there.  */
4015        __(bne local_label(nthrownv_skip))
4016        __(ldr imm0,[sp,#catch_frame.size+lisp_frame.savevsp])
4017        __(add imm1,vsp,nargs)
4018        __(movs arg_z,nargs)
4019        __(b local_label(nthrownv_push_test))
4020local_label(nthrownv_push_loop):       
4021        __(subs arg_z,arg_z,#fixnumone)
4022        __(ldr temp1,[imm1,#-node_size]!)
4023        __(push1(temp1,imm0))
4024local_label(nthrownv_push_test):       
4025        __(bne local_label(nthrownv_push_loop))
4026        __(mov vsp,imm0)
4027local_label(nthrownv_skip):     
4028        __(add sp,sp,#catch_frame.size+lisp_frame.size)
4029        __(b local_label(nthrownv_nextframe))               
4030local_label(nthrownv_do_unwind):
4031        __(ldr arg_x,[temp0,#catch_frame.xframe])
4032        __(ldr arg_z,[temp0,#catch_frame.last_lisp_frame])
4033        __(sub sp,temp0,#fulltag_misc)
4034        __(str arg_x,[rcontext,#tcr.xframe])
4035        __(str arg_z,[rcontext,#tcr.last_lisp_frame])
4036        __(add sp,sp,#catch_frame.size)
4037        __(add imm1,nargs,#node_size)
4038        __(mov arg_z,sp)
4039        __(dnode_align(imm0,imm1,node_size))
4040        __(mov imm1,imm1,lsl #num_subtag_bits-fixnumshift)
4041        __(orr imm1,imm1,#subtag_u32_vector)
4042        __(stack_allocate_zeroed_ivector(imm1,imm0))
4043        __(mov imm0,#subtag_simple_vector)
4044        __(strb imm0,[sp])
4045        __(str temp2,[sp,#node_size])
4046        __(add temp2,sp,#dnode_size)
4047        __(add temp2,temp2,nargs)
4048        __(add temp1,vsp,nargs)
4049        __(b local_label(nthrownv_tpushtest))
4050local_label(nthrownv_tpushloop):       
4051        __(ldr temp0,[temp1,#-node_size]!)
4052        __(push1(temp0,temp2))
4053local_label(nthrownv_tpushtest):       
4054        __(subs nargs,nargs,#fixnumone)
4055        __(bge local_label(nthrownv_tpushloop))
4056        __(mov imm1,#0)
4057        __(add imm0,arg_z,#lisp_frame.savelr)
4058        __(swp lr,lr,[imm0])
4059        __(ldr nfn,[arg_z,#lisp_frame.savefn])
4060        __(str fn,[arg_z,#lisp_frame.savefn])
4061        __(ldr vsp,[arg_z,#lisp_frame.savevsp])
4062        __(str imm1,[rcontext,#tcr.unwinding])
4063        __(mov fn,nfn)
4064        __(blx lr)
4065        __(mov imm1,#1)
4066        __(str imm1,[rcontext,#tcr.unwinding])
4067        __(ldr imm0,[sp])
4068        __(header_length(imm0,imm0))
4069        __(subs nargs,imm0,#node_size)
4070        __(add imm0,imm0,#node_size)
4071        __(add temp0,sp,imm0)
4072        __(mov imm0,nargs)
4073        __(add arg_z,temp0,#node_size)
4074        __(bic arg_z,arg_z,#fulltagmask)
4075        __(b local_label(nthrownv_tpoptest))
4076local_label(nthrownv_tpoploop): 
4077        __(subs imm0,imm0,#node_size)       
4078        __(vpush1(temp2))
4079local_label(nthrownv_tpoptest): 
4080        __(ldr temp2,[temp0,#-node_size]!)
4081        __(bne local_label(nthrownv_tpoploop))
4082        __(mov sp,arg_z)
4083        __(ldr fn,[sp,#lisp_frame.savefn])
4084        __(ldr lr,[sp,#lisp_frame.savelr])
4085        __(discard_lisp_frame())
4086        __(b local_label(nthrownv_nextframe))
4087local_label(nthrownv_done):     
4088        __(mov imm0,#0)
4089        __(str imm0,[rcontext,#tcr.unwinding])
4090        __(check_pending_interrupt(imm1))
4091        __(bx lr)
4092_endfn               
4093
4094_exportfn(C(progvsave))       
4095        /* Error if arg_z isn't a proper list.  That's unlikely, */
4096        /* but it's better to check now than to crash later. */
4097        __(cmp arg_z,#nil_value)
4098        __(mov arg_x,arg_z) /* fast  */
4099        __(mov temp1,arg_z) /* slow  */
4100        __(beq 9f)  /* Null list is proper  */
41010: 
4102        __(trap_unless_list(arg_x,imm0))
4103        __(_cdr(temp2,arg_x)) /* (null (cdr fast)) ?  */
4104        __(trap_unless_list(temp2,imm0,cr0))
4105        __(cmp temp2,#nil_value)
4106        __(_cdr(arg_x,temp2))
4107        __(beq 9f)
4108        __(_cdr(temp1,temp1))
4109        __(cmp arg_x,temp1)
4110        __(bne 0b)
4111        __(mov arg_y,#XIMPROPERLIST)
4112        __(set_nargs(2))
4113        __(b _SPksignalerr)
41149:      /* Whew   */
4115 
4116        /* Next, determine the length of arg_y.  We  */
4117        /* know that it's a proper list.  */
4118        __(mov imm0,#0)
4119        __(mov arg_x,arg_y)
41201:
4121        __(cmp arg_x,#nil_value)
4122        __(addne imm0,imm0,#node_size)
4123        __(_cdr(arg_x,arg_x))
4124        __(bne 1b)
4125        /* imm0 is now (boxed) triplet count.  */
4126        /* Determine word count, add 1 (to align), and make room.  */
4127        /* if count is 0, make an empty tsp frame and exit  */
4128        __(cmp imm0,#0)
4129        __(add imm1,imm0,imm0,lsl #1)
4130        __(add imm1,imm1,#node_size) /* Room for binding count */
4131        __(dnode_align(imm2,imm1,node_size))
4132        __(bne 2f)
4133        __(movc16(imm0,make_header(1,subtag_simple_vector)))
4134        __(mov imm1,#0)
4135        __(stmdb sp!,{imm0,imm1})
4136        __(b 9f)
41372:
4138        __(mov imm1,imm1,lsl #num_subtag_bits-fixnumshift)
4139        __(orr imm1,imm1,#subtag_u32_vector)
4140        __(mov temp1,sp)
4141        __(stack_allocate_zeroed_ivector(imm1,imm2))
4142        __(mov imm1,#subtag_simple_vector)
4143        __(strb imm1,[sp])
4144        __(str imm0,[sp,#node_size])
4145        __(ldr imm1,[rcontext,#tcr.db_link])
41463:      __(_car(temp0,arg_y))
4147        __(ldr imm0,[temp0,#symbol.binding_index])
4148        __(ldr imm2,[rcontext,#tcr.tlb_limit])
4149        __(_cdr(arg_y,arg_y))
4150        __(cmp imm2,imm0)
4151        __(uuo_tlb_too_small(ls,imm0))
4152        __(ldr arg_x,[rcontext,#tcr.tlb_pointer])
4153        __(ldr temp0,[arg_x,imm0])
4154        __(cmp arg_z,#nil_value)
4155        __(mov temp2,#unbound_marker)
4156        __(ldrne temp2,[arg_z,#cons.car])
4157        __(_cdr(arg_z,arg_z))
4158        __(cmp arg_y,#nil_value)
4159        __(push1(temp0,temp1))
4160        __(push1(imm0,temp1))
4161        __(push1(imm1,temp1))
4162        __(mov imm1,temp1)
4163        __(str temp2,[arg_x,imm0])
4164        __(bne 3b)
4165        __(str imm1,[rcontext,#tcr.db_link])
41669:             
4167        __(mov arg_z,#unbound_marker)
4168        __(mov imm2,#fixnum_one)
4169        __(mkcatch())       
4170        __(bx lr)
4171_endfn                               
4172               
4173/* Too large to safely fit on tstack.  Heap-cons the vector, but make  */
4174/* sure that there's an empty tsp frame to keep the compiler happy.  */
4175_exportfn(stack_misc_alloc_no_room)
4176        __(mov imm0,#stack_alloc_marker)
4177        __(mov imm1,sp)
4178        __(stmdb sp!,{imm0,imm1})
4179        __(b _SPmisc_alloc)
4180_endfn       
4181        _endfile
Note: See TracBrowser for help on using the repository browser.