source: branches/arm64/lisp-kernel/arm64-spentry.s @ 15550

Last change on this file since 15550 was 15550, checked in by gb, 8 years ago

Move along, nothing to see here. Honest.
Some the files (those that aren't missing ...) are empty; there's very
little in the way of actual ARMv8 code here, and there'll need to be
a lot more before this is even worth talking about.

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