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

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

Need to restore double-float-zero after ffcall.

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