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

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

In _SPconslist: cons arg_y and arg_z, not arg_z and itself.
In _SPstkconslist: add extra word to "vector" size, for alignment.

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