1 | /* Copyright (C) 2009 Clozure Associates */ |
---|
2 | /* Copyright (C) 1994-2001 Digitool, Inc */ |
---|
3 | /* This file is part of Clozure CL. */ |
---|
4 | |
---|
5 | /* Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */ |
---|
6 | /* License , known as the LLGPL and distributed with Clozure CL as the */ |
---|
7 | /* file "LICENSE". The LLGPL consists of a preamble and the LGPL, */ |
---|
8 | /* which is distributed with Clozure CL as the file "LGPL". Where these */ |
---|
9 | /* conflict, the preamble takes precedence. */ |
---|
10 | |
---|
11 | /* Clozure CL is referenced in the preamble as the "LIBRARY." */ |
---|
12 | |
---|
13 | /* The LLGPL is also available online at */ |
---|
14 | /* http://opensource.franz.com/preamble.html */ |
---|
15 | |
---|
16 | /* The assembler has to do the arithmetic here: the expression */ |
---|
17 | /* may not be evaluable by m4. */ |
---|
18 | |
---|
19 | |
---|
20 | |
---|
21 | |
---|
22 | /* dnode_align(dest,src,delta) */ |
---|
23 | define(`dnode_align',` |
---|
24 | __(add $1,[$2,#(dnode_size-1)]) |
---|
25 | __(bic $1,$1,#((1<<dnode_align_bits)-1)) |
---|
26 | ') |
---|
27 | |
---|
28 | define(`extract_fulltag',` |
---|
29 | __(and $1,$1,#((1<<ntagbits)-1)) |
---|
30 | ') |
---|
31 | |
---|
32 | define(`extract_lisptag',` |
---|
33 | __(and $1,$1,#((1<<nlisptagbits)-1)) |
---|
34 | ') |
---|
35 | |
---|
36 | define(`extract_lisptag_',` |
---|
37 | __(ands $1,$1,#((1<<nlisptagbits)-1)) |
---|
38 | ') |
---|
39 | |
---|
40 | define(`extract_subtag',` |
---|
41 | __(ldrb $1,[$2,#misc_subtag_offset]) |
---|
42 | ') |
---|
43 | |
---|
44 | |
---|
45 | define(`extract_lowbyte',` |
---|
46 | __(and $1,$2,#((1<<num_subtag_bits)-1)) |
---|
47 | ') |
---|
48 | |
---|
49 | define(`extract_header',` |
---|
50 | __(ldr $1,[$2,#misc_header_offset]) |
---|
51 | ') |
---|
52 | |
---|
53 | define(`extract_typecode',` |
---|
54 | __(extract_lisptag($1,$2)) |
---|
55 | __(cmp $1,#fulltag_misc) |
---|
56 | __(ldrbeq $1,[$2,#misc_subtag_offset]) |
---|
57 | ') |
---|
58 | |
---|
59 | define(`box_fixnum',` |
---|
60 | __(mov #1,$2 lsl #fixnumshift) |
---|
61 | ') |
---|
62 | |
---|
63 | define(`unbox_fixnum',` |
---|
64 | __(mov $1,$2 asr #fixnumshift) |
---|
65 | ') |
---|
66 | |
---|
67 | define(`loaddf',` |
---|
68 | __(lfd $1,dfloat.value($2))') |
---|
69 | |
---|
70 | define(`storedf',` |
---|
71 | __(stfd $1,dfloat.value($2)) |
---|
72 | ') |
---|
73 | |
---|
74 | define(`push',` |
---|
75 | __(stru($1,-node_size($2))) |
---|
76 | ') |
---|
77 | |
---|
78 | /* Generally not a great idea. */ |
---|
79 | define(`pop',` |
---|
80 | __(ldr($1,0($2))) |
---|
81 | __(la $2,node_size($2)) |
---|
82 | ') |
---|
83 | |
---|
84 | define(`vpush',` |
---|
85 | __(push($1,vsp)) |
---|
86 | ') |
---|
87 | |
---|
88 | define(`vpop',` |
---|
89 | __(pop($1,vsp)) |
---|
90 | ') |
---|
91 | |
---|
92 | |
---|
93 | define(`unlink',` |
---|
94 | __(ldr($1,0($1))) |
---|
95 | ') |
---|
96 | |
---|
97 | |
---|
98 | define(`set_nargs',` |
---|
99 | __(lwi(nargs,($1)<<fixnumshift)) |
---|
100 | ') |
---|
101 | |
---|
102 | define(`bitclr',` |
---|
103 | __(rlwinm $1,$2,0,0x1f&((31-($3))+1),0x1f&((31-($3))-1)) |
---|
104 | ') |
---|
105 | |
---|
106 | |
---|
107 | define(`vref32',` |
---|
108 | __(lwz $1,misc_data_offset+(($3)<<2)($2)) |
---|
109 | ') |
---|
110 | |
---|
111 | define(`vref16',`/* dest,src,n*/ |
---|
112 | __(lhz $1,misc_data_offset+(($3)<<1)($2)) |
---|
113 | ') |
---|
114 | |
---|
115 | ifdef(`PPC64',` |
---|
116 | define(`vref64',` |
---|
117 | __(ld $1,misc_data_offset+(($3)<<3)($2)) |
---|
118 | ') |
---|
119 | |
---|
120 | define(`vrefr',` |
---|
121 | __(vref64($1,$2,$3)) |
---|
122 | ') |
---|
123 | ',` |
---|
124 | define(`vrefr',` |
---|
125 | __(vref32($1,$2,$3)) |
---|
126 | ') |
---|
127 | ') |
---|
128 | |
---|
129 | |
---|
130 | define(`getvheader',` |
---|
131 | __(ldr($1,vector.header($2))) |
---|
132 | ') |
---|
133 | |
---|
134 | /* Size is unboxed element count */ |
---|
135 | define(`header_size',` |
---|
136 | __(srri($1,$2,num_subtag_bits)) |
---|
137 | ') |
---|
138 | |
---|
139 | /* "Length" is fixnum element count */ |
---|
140 | define(`header_length',` |
---|
141 | ifdef(`PPC64',` |
---|
142 | __(rldicr $1,$2,nbits_in_word-(num_subtag_bits-nfixnumtagbits),63-nfixnumtagbits) |
---|
143 | __(clrldi $1,$1,(num_subtag_bits-nfixnumtagbits)) |
---|
144 | ',` |
---|
145 | __(rlwinm $1,$2,nbits_in_word-(num_subtag_bits-nfixnumtagbits),(num_subtag_bits-nfixnumtagbits),31-nfixnumtagbits) |
---|
146 | ') |
---|
147 | ') |
---|
148 | |
---|
149 | |
---|
150 | define(`vector_size',` |
---|
151 | __(getvheader(ifelse($3.`',$1,$3),$2)) |
---|
152 | __(header_size($1,ifelse($3.`',$1,$3))) |
---|
153 | ') |
---|
154 | |
---|
155 | define(`vector_length',` |
---|
156 | __(getvheader($3,$2)) |
---|
157 | __(header_length($1,$3)) |
---|
158 | ') |
---|
159 | |
---|
160 | |
---|
161 | define(`ref_global',` |
---|
162 | __(ldr($1,lisp_globals.$2(0))) |
---|
163 | ') |
---|
164 | |
---|
165 | define(`set_global',` |
---|
166 | __(str($1,lisp_globals.$2(0))) |
---|
167 | ') |
---|
168 | |
---|
169 | define(`ref_nrs_value',` |
---|
170 | __(ldr($1,((nrs.$2)+(symbol.vcell))(0))) |
---|
171 | ') |
---|
172 | |
---|
173 | define(`set_nrs_value',` |
---|
174 | __(str($1,((nrs.$2)+(symbol.vcell))(0))) |
---|
175 | ') |
---|
176 | |
---|
177 | define(`extract_unsigned_byte_bits',` |
---|
178 | ifdef(`PPC64',` |
---|
179 | __(rldicr $1,$2,64-fixnumshift,63-$3) |
---|
180 | ',` |
---|
181 | __(rlwinm $1,$2,0,32-fixnumshift,31-($3+fixnumshift)) |
---|
182 | ') |
---|
183 | ') |
---|
184 | |
---|
185 | define(`extract_unsigned_byte_bits_',` |
---|
186 | ifdef(`PPC64',` |
---|
187 | __(rldicr. $1,$2,64-fixnumshift,63-$3) |
---|
188 | ',` |
---|
189 | __(rlwinm. $1,$2,0,32-fixnumshift,31-($3+fixnumshift)) |
---|
190 | ') |
---|
191 | ') |
---|
192 | |
---|
193 | /* vpop argregs - nargs is known to be non-zero */ |
---|
194 | define(`vpop_argregs_nz',` |
---|
195 | new_macro_labels() |
---|
196 | __(cmplri(cr1,nargs,node_size*2)) |
---|
197 | __(vpop(arg_z)) |
---|
198 | __(blt cr1,macro_label(l0)) |
---|
199 | __(vpop(arg_y)) |
---|
200 | __(bne cr1,macro_label(l0)) |
---|
201 | __(vpop(arg_x)) |
---|
202 | macro_label(l0):') |
---|
203 | |
---|
204 | |
---|
205 | /* vpush argregs */ |
---|
206 | define(`vpush_argregs',` |
---|
207 | new_macro_labels() |
---|
208 | __(cmplri(cr0,nargs,0)) |
---|
209 | __(cmplri(cr1,nargs,node_size*2)) |
---|
210 | __(beq cr0,macro_label(done)) |
---|
211 | __(blt cr1,macro_label(z)) |
---|
212 | __(beq cr1,macro_label(yz)) |
---|
213 | __(vpush(arg_x)) |
---|
214 | macro_label(yz): |
---|
215 | __(vpush(arg_y)) |
---|
216 | macro_label(z): |
---|
217 | __(vpush(arg_z)) |
---|
218 | macro_label(done): |
---|
219 | ') |
---|
220 | |
---|
221 | define(`create_lisp_frame',` |
---|
222 | __(stru(sp,-lisp_frame.size(sp))) |
---|
223 | ') |
---|
224 | |
---|
225 | |
---|
226 | define(`build_lisp_frame',` |
---|
227 | create_lisp_frame() |
---|
228 | __(str(ifelse($1,`',fn,$1),lisp_frame.savefn(sp))) |
---|
229 | __(str(ifelse($2,`',loc_pc,$2),lisp_frame.savelr(sp))) |
---|
230 | __(str(ifelse($3,`',vsp,$3),lisp_frame.savevsp(sp))) |
---|
231 | ') |
---|
232 | |
---|
233 | |
---|
234 | define(`discard_lisp_frame',` |
---|
235 | __(la sp,lisp_frame.size(sp)) |
---|
236 | ') |
---|
237 | |
---|
238 | |
---|
239 | define(`_car',` |
---|
240 | __(ldr($1,cons.car($2))) |
---|
241 | ') |
---|
242 | |
---|
243 | define(`_cdr',` |
---|
244 | __(ldr($1,cons.cdr($2))) |
---|
245 | ') |
---|
246 | |
---|
247 | define(`_rplaca',` |
---|
248 | __(str($2,cons.car($1))) |
---|
249 | ') |
---|
250 | |
---|
251 | define(`_rplacd',` |
---|
252 | __(str($2,cons.cdr($1))) |
---|
253 | ') |
---|
254 | |
---|
255 | define(`vpush_saveregs',` |
---|
256 | __(vpush(save7)) |
---|
257 | __(vpush(save6)) |
---|
258 | __(vpush(save5)) |
---|
259 | __(vpush(save4)) |
---|
260 | __(vpush(save3)) |
---|
261 | __(vpush(save2)) |
---|
262 | __(vpush(save1)) |
---|
263 | __(vpush(save0)) |
---|
264 | ') |
---|
265 | |
---|
266 | define(`restore_saveregs',` |
---|
267 | __(ldr(save0,node_size*0($1))) |
---|
268 | __(ldr(save1,node_size*1($1))) |
---|
269 | __(ldr(save2,node_size*2($1))) |
---|
270 | __(ldr(save3,node_size*3($1))) |
---|
271 | __(ldr(save4,node_size*4($1))) |
---|
272 | __(ldr(save5,node_size*5($1))) |
---|
273 | __(ldr(save6,node_size*6($1))) |
---|
274 | __(ldr(save7,node_size*7($1))) |
---|
275 | ') |
---|
276 | |
---|
277 | define(`vpop_saveregs',` |
---|
278 | __(restore_saveregs(vsp)) |
---|
279 | __(la vsp,node_size*8(vsp)) |
---|
280 | ') |
---|
281 | |
---|
282 | define(`trap_unless_lisptag_equal',` |
---|
283 | __(extract_lisptag($3,$1)) |
---|
284 | __(trnei($3,$2)) |
---|
285 | ') |
---|
286 | |
---|
287 | ifdef(`PPC64',` |
---|
288 | define(`trap_unless_list',` |
---|
289 | new_macro_labels() |
---|
290 | __(cmpdi ifelse($3,$3,cr0),$1,nil_value) |
---|
291 | __(extract_fulltag($2,$1)) |
---|
292 | __(beq ifelse($3,$3,cr0),macro_label(is_list)) |
---|
293 | __(tdnei $2,fulltag_cons) |
---|
294 | macro_label(is_list): |
---|
295 | |
---|
296 | ')',` |
---|
297 | define(`trap_unless_list',` |
---|
298 | __(trap_unless_lisptag_equal($1,tag_list,$2)) |
---|
299 | ') |
---|
300 | ') |
---|
301 | |
---|
302 | define(`trap_unless_fulltag_equal',` |
---|
303 | __(extract_fulltag($3,$1)) |
---|
304 | __(trnei($3,$2)) |
---|
305 | ') |
---|
306 | |
---|
307 | define(`trap_unless_typecode_equal',` |
---|
308 | __(extract_typecode($3,$1)) |
---|
309 | __(trnei($3,$2)) |
---|
310 | ') |
---|
311 | |
---|
312 | /* "jump" to the code-vector of the function in nfn. */ |
---|
313 | define(`jump_nfn',` |
---|
314 | __(ldr(temp0,_function.codevector(nfn))) |
---|
315 | __(mtctr temp0) |
---|
316 | __(bctr) |
---|
317 | ') |
---|
318 | |
---|
319 | /* "call the code-vector of the function in nfn. */ |
---|
320 | define(`call_nfn',` |
---|
321 | __(ldr(temp0,_function.codevector(nfn))) |
---|
322 | __(mtctr temp0) |
---|
323 | __(bctrl) |
---|
324 | ') |
---|
325 | |
---|
326 | |
---|
327 | /* "jump" to the function in fnames function cell. */ |
---|
328 | define(`jump_fname',` |
---|
329 | __(ldr(nfn,symbol.fcell(fname))) |
---|
330 | __(jump_nfn()) |
---|
331 | ') |
---|
332 | |
---|
333 | /* call the function in fnames function cell. */ |
---|
334 | define(`call_fname',` |
---|
335 | __(ldr(nfn,symbol.fcell(fname))) |
---|
336 | __(call_nfn()) |
---|
337 | ') |
---|
338 | |
---|
339 | define(`do_funcall',` |
---|
340 | new_macro_labels() |
---|
341 | __(extract_fulltag(imm0,temp0)) |
---|
342 | __(cmpri(imm0,fulltag_misc)) |
---|
343 | __(mr nfn,temp0) |
---|
344 | __(bne- macro_label(bad)) |
---|
345 | __(extract_subtag(imm0,temp0)) |
---|
346 | __(cmpri(imm0,subtag_function)) |
---|
347 | __(cmpri(cr1,imm0,subtag_symbol)) |
---|
348 | __(bne cr0,macro_label(_sym)) |
---|
349 | __(jump_nfn()) |
---|
350 | macro_label(_sym): |
---|
351 | __(mr fname,temp0) |
---|
352 | __(bne cr1,macro_label(bad)) |
---|
353 | __(jump_fname()) |
---|
354 | macro_label(bad): |
---|
355 | __(uuo_interr(error_cant_call,temp0)) |
---|
356 | ') |
---|
357 | |
---|
358 | define(`mkcatch',` |
---|
359 | __(mflr loc_pc) |
---|
360 | __(ldr(imm0,tcr.catch_top(rcontext))) |
---|
361 | __(lwz imm1,0(loc_pc)) /* a forward branch to the catch/unwind cleanup */ |
---|
362 | __(rlwinm imm1,imm1,0,6,29) /* extract LI */ |
---|
363 | __(add loc_pc,loc_pc,imm1) |
---|
364 | __(build_lisp_frame(fn,loc_pc,vsp)) |
---|
365 | __(sub loc_pc,loc_pc,imm1) |
---|
366 | __(la loc_pc,4(loc_pc)) /* skip over the forward branch */ |
---|
367 | __(mtlr loc_pc) |
---|
368 | __(lwi(imm4,(catch_frame.element_count<<num_subtag_bits)|subtag_catch_frame)) |
---|
369 | __(ldr(imm3,tcr.xframe(rcontext))) |
---|
370 | __(ldr(imm1,tcr.db_link(rcontext))) |
---|
371 | __(TSP_Alloc_Fixed_Unboxed(catch_frame.size)) |
---|
372 | __(la nargs,tsp_frame.data_offset+fulltag_misc(tsp)) |
---|
373 | __(str(imm4,catch_frame.header(nargs))) |
---|
374 | __(str(arg_z,catch_frame.catch_tag(nargs))) |
---|
375 | __(str(imm0,catch_frame.link(nargs))) |
---|
376 | __(str(imm2,catch_frame.mvflag(nargs))) |
---|
377 | __(str(sp,catch_frame.csp(nargs))) |
---|
378 | __(str(imm1,catch_frame.db_link(nargs))) |
---|
379 | __(str(first_nvr,catch_frame.regs+0*node_size(nargs))) |
---|
380 | __(str(second_nvr,catch_frame.regs+1*node_size(nargs))) |
---|
381 | __(str(third_nvr,catch_frame.regs+2*node_size(nargs))) |
---|
382 | __(str(fourth_nvr,catch_frame.regs+3*node_size(nargs))) |
---|
383 | __(str(fifth_nvr,catch_frame.regs+4*node_size(nargs))) |
---|
384 | __(str(sixth_nvr,catch_frame.regs+5*node_size(nargs))) |
---|
385 | __(str(seventh_nvr,catch_frame.regs+6*node_size(nargs))) |
---|
386 | __(str(eighth_nvr,catch_frame.regs+7*node_size(nargs))) |
---|
387 | __(str(imm3,catch_frame.xframe(nargs))) |
---|
388 | __(str(rzero,catch_frame.tsp_segment(nargs))) |
---|
389 | __(Set_TSP_Frame_Boxed()) |
---|
390 | __(str(nargs,tcr.catch_top(rcontext))) |
---|
391 | __(li nargs,0) |
---|
392 | |
---|
393 | ') |
---|
394 | |
---|
395 | define(`restore_catch_nvrs',` |
---|
396 | __(ldr(first_nvr,catch_frame.regs+(node_size*0)($1))) |
---|
397 | __(ldr(second_nvr,catch_frame.regs+(node_size*1)($1))) |
---|
398 | __(ldr(third_nvr,catch_frame.regs+(node_size*2)($1))) |
---|
399 | __(ldr(fourth_nvr,catch_frame.regs+(node_size*3)($1))) |
---|
400 | __(ldr(fifth_nvr,catch_frame.regs+(node_size*4)($1))) |
---|
401 | __(ldr(sixth_nvr,catch_frame.regs+(node_size*5)($1))) |
---|
402 | __(ldr(seventh_nvr,catch_frame.regs+(node_size*6)($1))) |
---|
403 | __(ldr(eighth_nvr,catch_frame.regs+(node_size*7)($1))) |
---|
404 | ') |
---|
405 | |
---|
406 | define(`DCBZL',` |
---|
407 | __(.long (31<<26)+(1<<21)+($1<<16)+($2<<11)+(1014<<1)) |
---|
408 | ') |
---|
409 | |
---|
410 | define(`check_stack_alignment',` |
---|
411 | new_macro_labels() |
---|
412 | __(andi. $1,sp,STACK_ALIGN_MASK) |
---|
413 | __(beq+ macro_label(stack_ok)) |
---|
414 | __(.long 0) |
---|
415 | macro_label(stack_ok): |
---|
416 | ') |
---|
417 | |
---|
418 | define(`stack_align',`((($1)+STACK_ALIGN_MASK)&~STACK_ALIGN_MASK)') |
---|
419 | |
---|
420 | define(`clear_alloc_tag',` |
---|
421 | __(clrrri(allocptr,allocptr,ntagbits)) |
---|
422 | ') |
---|
423 | |
---|
424 | /* If the GC interrupts the current thread (after the trap), it needs */ |
---|
425 | /* to ensure that the cons cell that's been "reserved" stays reserved */ |
---|
426 | /* (e.g. the tagged allocptr has to be treated as a node.) If that */ |
---|
427 | /* reserved cons cell gets tenured, the car and cdr are of a generation */ |
---|
428 | /* that's at least as old (so memoization isn't an issue.) */ |
---|
429 | |
---|
430 | /* More generally, if the GC interrupts a thread when allocptr is */ |
---|
431 | /* tagged as a cons: */ |
---|
432 | |
---|
433 | /* a) if the trap hasn't been taken (yet), the GC should force the */ |
---|
434 | /* thread to resume in such a way that the trap will be taken ; */ |
---|
435 | /* the segment allocator should worry about allocating the object. */ |
---|
436 | |
---|
437 | /* b) If the trap has been taken, allocptr is treated as a node as */ |
---|
438 | /* described above. Allocbase is made to point to the base of the */ |
---|
439 | /* cons cell, so that the thread's next allocation attempt will */ |
---|
440 | /* invoke the segment allocator. */ |
---|
441 | |
---|
442 | define(`Cons',` |
---|
443 | __(la allocptr,(-cons.size+fulltag_cons)(allocptr)) |
---|
444 | __(alloc_trap()) |
---|
445 | __(str($3,cons.cdr(allocptr))) |
---|
446 | __(str($2,cons.car(allocptr))) |
---|
447 | __(mr $1,allocptr) |
---|
448 | __(clear_alloc_tag()) |
---|
449 | ') |
---|
450 | |
---|
451 | |
---|
452 | /* This is probably only used once or twice in the entire kernel, but */ |
---|
453 | /* I wanted a place to describe the constraints on the mechanism. */ |
---|
454 | |
---|
455 | /* Those constaints are (not surprisingly) similar to those which apply */ |
---|
456 | /* to cons cells, except for the fact that the header (and any length */ |
---|
457 | /* field that might describe large arrays) has to have been stored in */ |
---|
458 | /* the object if the trap has succeeded on entry to the GC. It follows */ |
---|
459 | /* that storing the register containing the header must immediately */ |
---|
460 | /* follow the allocation trap (and an auxiliary length register must */ |
---|
461 | /* be stored immediately after the header.) Successfully falling */ |
---|
462 | /* through the trap must emulate any header initialization: it would */ |
---|
463 | /* be a bad idea to have allocptr pointing to a zero header ... */ |
---|
464 | |
---|
465 | |
---|
466 | |
---|
467 | /* Parameters: */ |
---|
468 | |
---|
469 | /* $1 = dest reg */ |
---|
470 | /* $2 = header. (For now, assume that this always encodes length ; */ |
---|
471 | /* that may change with "large vector" support.) */ |
---|
472 | /* $3 = register containing size in bytes. (We're going to subtract */ |
---|
473 | /* fulltag_misc from this; do it in the macro body, rather than force the |
---|
474 | /* (1 ?) caller to do it. */ |
---|
475 | |
---|
476 | |
---|
477 | define(`Misc_Alloc',` |
---|
478 | __(la $3,-fulltag_misc($3)) |
---|
479 | __(sub allocptr,allocptr,$3) |
---|
480 | __(alloc_trap()) |
---|
481 | __(str($2,misc_header_offset(allocptr))) |
---|
482 | __(mr $1,allocptr) |
---|
483 | __(clear_alloc_tag()) |
---|
484 | ') |
---|
485 | |
---|
486 | /* Parameters $1, $2 as above; $3 = physical size constant. */ |
---|
487 | define(`Misc_Alloc_Fixed',` |
---|
488 | __(la allocptr,(-$3)+fulltag_misc(allocptr)) |
---|
489 | __(alloc_trap()) |
---|
490 | __(str($2,misc_header_offset(allocptr))) |
---|
491 | __(mr $1,allocptr) |
---|
492 | __(clear_alloc_tag()) |
---|
493 | ') |
---|
494 | |
---|
495 | |
---|
496 | /* Zero $3 bytes worth of doublewords, starting at offset $2 relative */ |
---|
497 | /* to the base register $1. */ |
---|
498 | |
---|
499 | |
---|
500 | ifdef(`DARWIN',` |
---|
501 | .macro zero_doublewords |
---|
502 | .if $2 |
---|
503 | stfd fp_zero,$1($0) |
---|
504 | zero_doublewords $0,$1+8,$2-8 |
---|
505 | .endif |
---|
506 | .endmacro |
---|
507 | ') |
---|
508 | |
---|
509 | ifdef(`LINUX',` |
---|
510 | .macro zero_doublewords base,disp,nbytes |
---|
511 | .if \nbytes |
---|
512 | stfd fp_zero,\disp(\base) |
---|
513 | zero_doublewords \base,\disp+8,\nbytes-8 |
---|
514 | .endif |
---|
515 | .endm |
---|
516 | ') |
---|
517 | |
---|
518 | define(`Set_TSP_Frame_Unboxed',` |
---|
519 | __(str(tsp,tsp_frame.type(tsp))) |
---|
520 | ') |
---|
521 | |
---|
522 | define(`Set_TSP_Frame_Boxed',` |
---|
523 | __(str(rzero,tsp_frame.type(tsp))) |
---|
524 | ') |
---|
525 | |
---|
526 | /* A newly allocated TSP frame is always "raw" (has non-zero type, indicating */ |
---|
527 | /* that it doesn't contain tagged data. */ |
---|
528 | |
---|
529 | define(`TSP_Alloc_Fixed_Unboxed',` |
---|
530 | __(stru(tsp,-($1+tsp_frame.data_offset)(tsp))) |
---|
531 | __(Set_TSP_Frame_Unboxed()) |
---|
532 | ') |
---|
533 | |
---|
534 | define(`TSP_Alloc_Fixed_Unboxed_Zeroed',` |
---|
535 | __(TSP_Alloc_Fixed_Unboxed($1)) |
---|
536 | __(zero_doublewords tsp,tsp_frame.fixed_overhead,$1) |
---|
537 | ') |
---|
538 | |
---|
539 | define(`TSP_Alloc_Fixed_Boxed',` |
---|
540 | __(TSP_Alloc_Fixed_Unboxed_Zeroed($1)) |
---|
541 | __(Set_TSP_Frame_Boxed()) |
---|
542 | ') |
---|
543 | |
---|
544 | |
---|
545 | |
---|
546 | |
---|
547 | |
---|
548 | /* This assumes that the backpointer points to the first byte beyond */ |
---|
549 | /* each frame. If we allow segmented tstacks, that constraint might */ |
---|
550 | /* complicate their implementation. */ |
---|
551 | /* We don't need to know the size of the frame (positive or negative, */ |
---|
552 | /* with or without header). $1 and $2 are temp registers, $3 is an */ |
---|
553 | /* optional CR field. */ |
---|
554 | |
---|
555 | |
---|
556 | /* Handle the general case, where the frame might be empty */ |
---|
557 | define(`Zero_TSP_Frame',` |
---|
558 | __(new_macro_labels()) |
---|
559 | __(la $1,tsp_frame.size-8(tsp)) |
---|
560 | __(ldr($2,tsp_frame.backlink(tsp))) |
---|
561 | __(la $2,-8($2)) |
---|
562 | __(b macro_label(zero_tsp_test)) |
---|
563 | macro_label(zero_tsp_loop): |
---|
564 | __(stfdu fp_zero,8($1)) |
---|
565 | macro_label(zero_tsp_test): |
---|
566 | __(cmpr(ifelse($3,`',`cr0',$3),$1,$2)) |
---|
567 | __(bne ifelse($3,`',`cr0',$3),macro_label(zero_tsp_loop)) |
---|
568 | ') |
---|
569 | |
---|
570 | /* Save some branching when we know that the frame can't be empty.*/ |
---|
571 | define(`Zero_TSP_Frame_nz',` |
---|
572 | new_macro_labels() |
---|
573 | __(la $1,tsp_frame.size-8(tsp)) |
---|
574 | __(ldr($2,tsp_frame.backlink(tsp))) |
---|
575 | __(la $2,-8($2)) |
---|
576 | macro_label(zero_tsp_loop): |
---|
577 | __(stfdu fp_zero,8($1)) |
---|
578 | __(cmpr(ifelse($3,`',`cr0',$3),$1,$2)) |
---|
579 | __(bne ifelse($3,`',`cr0',$3),macro_label(zero_tsp_loop)) |
---|
580 | ') |
---|
581 | |
---|
582 | /* $1 = 8-byte-aligned size, positive. $2 (optiional) set */ |
---|
583 | /* to negated size. */ |
---|
584 | define(`TSP_Alloc_Var_Unboxed',` |
---|
585 | __(neg ifelse($2,`',$1,$2),$1) |
---|
586 | __(strux(tsp,tsp,ifelse($2,`',$1,$2))) |
---|
587 | __(Set_TSP_Frame_Unboxed()) |
---|
588 | ') |
---|
589 | |
---|
590 | define(`TSP_Alloc_Var_Boxed',` |
---|
591 | __(TSP_Alloc_Var_Unboxed($1)) |
---|
592 | __(Zero_TSP_Frame($1,$2)) |
---|
593 | __(Set_TSP_Frame_Boxed()) |
---|
594 | ') |
---|
595 | |
---|
596 | |
---|
597 | define(`TSP_Alloc_Var_Boxed_nz',` |
---|
598 | __(TSP_Alloc_Var_Unboxed($1)) |
---|
599 | __(Zero_TSP_Frame_nz($1,$2)) |
---|
600 | __(Set_TSP_Frame_Boxed()) |
---|
601 | ') |
---|
602 | |
---|
603 | define(`check_pending_interrupt',` |
---|
604 | new_macro_labels() |
---|
605 | __(ldr(nargs,tcr.tlb_pointer(rcontext))) |
---|
606 | __(ldr(nargs,INTERRUPT_LEVEL_BINDING_INDEX(nargs))) |
---|
607 | __(cmpri(ifelse($1,`',`cr0',$1),nargs,0)) |
---|
608 | __(blt ifelse($1,`',`cr0',$1),macro_label(done)) |
---|
609 | __(bgt ifelse($1,`',`cr0',$1),macro_label(trap)) |
---|
610 | __(ldr(nargs,tcr.interrupt_pending(rcontext))) |
---|
611 | macro_label(trap): |
---|
612 | __(trgti(nargs,0)) |
---|
613 | macro_label(done): |
---|
614 | ') |
---|
615 | |
---|
616 | /* $1 = ndigits. Assumes 4-byte digits */ |
---|
617 | define(`aligned_bignum_size',`((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))') |
---|
618 | |
---|
619 | define(`suspend_now',` |
---|
620 | __(uuo_interr(error_propagate_suspend,rzero)) |
---|
621 | ') |
---|