source: trunk/source/lisp-kernel/x86-macros.s @ 11556

Last change on this file since 11556 was 11556, checked in by rme, 11 years ago

Change the x86 consing sequence to use ja (instead of jg) after comparing
tcr.save_allocptr and tcr.save_allocbase. (If we can manage to reserve
a bigger chunk of heap space, it might happen that these two values differ
in sign, i.e., tcr.save_allocptr might be above #x80000000 and
tcr.save_allocbase below. Of course, it may be a few years yet
before we have to start worrying about crossing #x8000000000000000 on
the x86-64 port...)

Update %ALLOCATE-UVECTOR and CONS vinsns, the Cons and Misc_Alloc_Internal
macros used in subprims, and the %WALK-DYNAMIC-AREA LAP function.

Also change pc_luser_xp() to recognize the ja instruction. (It still
recognizes the jg too, but treats it as ja when emulating it.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.9 KB
Line 
1/*   Copyright (C) 2005 Clozure Associates  */
2/*   This file is part of OpenMCL.    */
3
4/*   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public  */
5/*   License , known as the LLGPL and distributed with OpenMCL as the  */
6/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
7/*   which is distributed with OpenMCL as the file "LGPL".  Where these  */
8/*   conflict, the preamble takes precedence.    */
9
10/*   OpenMCL 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/* Try to make macros follow GAS/ATT conventions, where source precedes  */
17/* destination.  */
18
19define([lisp_global],[lisp_globals.$1])
20                                       
21define([ref_global],[
22        __(mov lisp_global($1),$2)
23])
24
25define([set_global],[
26        __(mov $1,lisp_global($2))
27])
28
29define([ref_nrs_value],[
30        __(mov nrs.$1+symbol.vcell,$2)
31])
32       
33define([set_nrs_value],[
34        __(mov $1,nrs.$2+symbol.vcell)
35])
36                                                       
37define([unbox_fixnum],[
38        __(mov $1,$2)
39        __(sar [$]fixnumshift,$2)
40])
41
42define([box_fixnum],[
43        __(imul [$]fixnumone,$1,$2)
44])     
45
46
47/* box_fixnum, with no effect on flags */
48define([box_fixnum_no_flags],[
49        __(lea (,$1,fixnumone),$2)
50])
51
52
53/* Zero $3 bytes worth of dnodes, starting at offset $2 relative  */
54/* to the base register $1.  */
55
56
57ifdef([DarwinAssembler],[
58        .macro zero_dnodes
59        .if $2
60        ifdef([X8664],[
61        __(movapd %fpzero,$1($0))
62        ],[
63        __(movsd %fpzero,$1($0))
64        ])
65        __(zero_dnodes $0,$1+dnode_size,$2-dnode_size)
66        .endif
67        .endmacro
68],[
69        .macro zero_dnodes base,disp,nbytes
70        .ifgt \nbytes
71        ifdef([X8664],[
72        movapd %fpzero,\disp(\base)
73        ],[
74        movsd %fpzero,\disp(\base)
75        ])
76        zero_dnodes \base,"\disp+dnode_size","\nbytes-dnode_size"
77        .endif
78        .endm
79])     
80
81
82/* Allocate $1+dnode_size zeroed bytes on the tstack, using $2 as a temp  */
83/* reg.  */
84
85ifdef([X8632],[
86define([TSP_Alloc_Fixed],[
87        define([TSP_Alloc_Size],[((($1+node_size) & ~(dnode_size-1))+dnode_size)])
88        __(subl [$]TSP_Alloc_Size,rcontext(tcr.next_tsp))
89        __(movd rcontext(tcr.save_tsp),%stack_temp)
90        __(movl rcontext(tcr.next_tsp),$2)
91        zero_dnodes $2,0,TSP_Alloc_Size
92        __(movd %stack_temp,($2))
93        __(movl %ebp,tsp_frame.save_ebp($2))
94        __(movl $2,rcontext(tcr.save_tsp))
95        undefine([TSP_Alloc_Size])
96])],[
97define([TSP_Alloc_Fixed],[
98        define([TSP_Alloc_Size],[((($1+node_size) & ~(dnode_size-1))+dnode_size)])
99        __(subq [$]TSP_Alloc_Size,rcontext(tcr.next_tsp))
100        __(movq rcontext(tcr.save_tsp),%stack_temp)
101        __(movq rcontext(tcr.next_tsp),$2)
102        zero_dnodes $2,0,TSP_Alloc_Size
103        __(movq %stack_temp,($2))
104        __(movq %rbp,tsp_frame.save_rbp($2))
105        __(movq $2,rcontext(tcr.save_tsp))
106        undefine([TSP_Alloc_Size])
107])])
108
109/* $1 = size (dnode-aligned, including tsp overhead, $2 scratch.  */
110/* Modifies both $1 and $2; on exit, $2 = new_tsp+tsp_overhead, $1 = old tsp  */
111
112ifdef([X8632],[
113define([TSP_Alloc_Var],[
114        new_macro_labels()
115        __(subl $1,rcontext(tcr.next_tsp))
116        __(movd rcontext(tcr.save_tsp),%stack_temp)
117        __(movl rcontext(tcr.next_tsp),$2)
118        __(jmp macro_label(test))
119macro_label(loop):
120        __(movsd %fpzero,0($2))
121        __(addl $dnode_size,$2)
122macro_label(test):
123        __(subl $dnode_size,$1)
124        __(jge macro_label(loop))
125        __(movl rcontext(tcr.next_tsp),$2)
126        __(movd %stack_temp,$1)
127        __(movl $1,($2))
128        __(movl %ebp,tsp_frame.save_ebp($2))
129        __(movl $2,rcontext(tcr.save_tsp))
130        __(addl $dnode_size,$2)
131])],[
132define([TSP_Alloc_Var],[
133        new_macro_labels()
134        subq $1,rcontext(tcr.next_tsp)
135        __(movq rcontext(tcr.save_tsp),%stack_temp)
136        __(movq rcontext(tcr.next_tsp),$2)
137        __(jmp macro_label(test))
138macro_label(loop):
139        __(movapd %fpzero,0($2))
140        __(addq $dnode_size,$2)
141macro_label(test):     
142        __(subq $dnode_size,$1)
143        __(jge macro_label(loop))
144        __(movq rcontext(tcr.next_tsp),$2)
145        __(movd %stack_temp,$1)
146        __(movq $1,($2))
147        __(movq %rbp,tsp_frame.save_rbp($2))
148        __(movq $2,rcontext(tcr.save_tsp))
149        __(addq $dnode_size,$2)
150])])
151       
152       
153ifdef([X8632],[
154define([Allocate_Catch_Frame],[
155        TSP_Alloc_Fixed(catch_frame.size,$1)
156        __(movl [$](catch_frame.element_count<<subtag_shift)|subtag_catch_frame,dnode_size($1))
157        __(addl [$]dnode_size+fulltag_misc,$1)
158])],[
159define([Allocate_Catch_Frame],[
160        TSP_Alloc_Fixed(catch_frame.size,$1)
161        __(movq [$](catch_frame.element_count<<subtag_shift)|subtag_catch_frame,dnode_size($1))
162        __(addq [$]dnode_size+fulltag_misc,$1)
163])])
164
165/* %arg_z = tag,  %xfn = pc, $1 = mvflag          */
166
167ifdef([X8632],[
168define([Make_Catch],[
169        Allocate_Catch_Frame(%imm0)
170        __(movd rcontext(tcr.catch_top),%mm0)
171        __(movd rcontext(tcr.db_link),%mm1)
172        __(movl %arg_z,catch_frame.catch_tag(%imm0))
173        __(movd %mm0,catch_frame.link(%imm0))
174        __(movl [$]$1,catch_frame.mvflag(%imm0))
175        __(movd rcontext(tcr.xframe),%mm0)
176        __(movl %esp,catch_frame.esp(%imm0))
177        __(movl %ebp,catch_frame.ebp(%imm0))
178        __(movd rcontext(tcr.foreign_sp),%stack_temp)
179        __(movd %stack_temp,catch_frame.foreign_sp(%imm0))
180        __(movd %mm1,catch_frame.db_link(%imm0))
181        __(movd %mm0,catch_frame.xframe(%imm0))
182        __(movl %xfn,catch_frame.pc(%imm0))
183        __(movl %imm0,rcontext(tcr.catch_top))
184])],[
185define([Make_Catch],[
186        Allocate_Catch_Frame(%imm2)
187        __(movq rcontext(tcr.catch_top),%imm0)
188        __(movq rcontext(tcr.db_link),%imm1)
189        __(movq %arg_z,catch_frame.catch_tag(%imm2))
190        __(movq %imm0,catch_frame.link(%imm2))
191        __(movq [$]$1,catch_frame.mvflag(%imm2))
192        __(movq rcontext(tcr.xframe),%imm0)
193        __(movq %rsp,catch_frame.rsp(%imm2))
194        __(movq %rbp,catch_frame.rbp(%imm2))
195        __(movq rcontext(tcr.foreign_sp),%stack_temp)
196        __(movq %imm1,catch_frame.db_link(%imm2))
197        __ifndef([WINDOWS])
198        __(movq %save3,catch_frame._save3(%imm2))
199        __endif
200        __(movq %save2,catch_frame._save2(%imm2))
201        __(movq %save1,catch_frame._save1(%imm2))
202        __(movq %save0,catch_frame._save0(%imm2))
203        __(movq %imm0,catch_frame.xframe(%imm2))
204        __(movq %stack_temp,catch_frame.foreign_sp(%imm2))
205        __(movq %xfn,catch_frame.pc(%imm2))
206        __(movq %imm2,rcontext(tcr.catch_top))
207])])   
208
209ifdef([X8632],[
210define([nMake_Catch],[
211        Allocate_Catch_Frame(%imm0)
212        __(movd rcontext(tcr.catch_top),%mm0)
213        __(movd rcontext(tcr.db_link),%mm1)
214        __(movl %arg_z,catch_frame.catch_tag(%imm0))
215        __(movd %mm0,catch_frame.link(%imm0))
216        __(movl %esp,catch_frame.esp(%imm0))
217        __(addl $node_size,catch_frame.esp(%imm0))
218        __(movl [$]$1,catch_frame.mvflag(%imm0))
219        __(movd rcontext(tcr.xframe),%mm0)
220        __(movl %ebp,catch_frame.ebp(%imm0))
221        __(movd rcontext(tcr.foreign_sp),%stack_temp)
222        __(movd %mm1,catch_frame.db_link(%imm0))
223        __(movd %mm0,catch_frame.xframe(%imm0))
224        __(movd %stack_temp,catch_frame.foreign_sp(%imm0))
225        __(movl %xfn,catch_frame.pc(%imm0))
226        __(movl %imm0,rcontext(tcr.catch_top))
227])],[   
228define([nMake_Catch],[
229        Allocate_Catch_Frame(%imm2)
230        __(movq rcontext(tcr.catch_top),%imm0)
231        __(movq rcontext(tcr.db_link),%imm1)
232        __(movq %arg_z,catch_frame.catch_tag(%imm2))
233        __(movq %imm0,catch_frame.link(%imm2))
234        __(lea node_size(%rsp),%imm0)
235        __(movq [$]$1,catch_frame.mvflag(%imm2))
236        __(movq %imm0,catch_frame.rsp(%imm2))
237        __(movq rcontext(tcr.xframe),%imm0)
238        __(movq %rbp,catch_frame.rbp(%imm2))
239        __(movq rcontext(tcr.foreign_sp),%stack_temp)
240        __(movq %imm1,catch_frame.db_link(%imm2))
241        __ifndef([WINDOWS])
242        __(movq %save3,catch_frame._save3(%imm2))
243        __endif
244        __(movq %save2,catch_frame._save2(%imm2))
245        __(movq %save1,catch_frame._save1(%imm2))
246        __(movq %save0,catch_frame._save0(%imm2))
247        __(movq %imm0,catch_frame.xframe(%imm2))
248        __(movq %stack_temp,catch_frame.foreign_sp(%imm2))
249        __(movq %xfn,catch_frame.pc(%imm2))
250        __(movq %imm2,rcontext(tcr.catch_top))
251])])   
252               
253       
254/* Consing can get interrupted (either by PROCESS-INTERRUPT or by GC  */
255/* activity in some other thread; if it's interrupted, the interrupting  */
256/* process needs to be able to determine what's going on well enough  */
257/* to be able to either back out of the attempt or finish the job.  */
258/* That requires that we use easily recogninized instruction sequences  */
259/* and follow certain conventions when consing (either in the kernel  */
260/* or in compiled code.)  (One of those conventions involves using  */
261/* %allocptr = %temp0 as a freepointer; when consing, %temp0 can't  */
262/* contain a live value.)  */
263/* Making a CONS cell is a little simpler than making a uvector.  */
264
265/* $1=new_car,$2=new_cdr,$3=dest   */
266
267ifdef([X8632],[
268define([Cons],[
269        new_macro_labels()
270/* The instructions where tcr.save_allocptr is tagged are difficult  */
271/* to interrupt; the interrupting code has to recognize and possibly  */
272/* emulate the instructions in between   */
273        __(subl $cons.size-fulltag_cons,rcontext(tcr.save_allocptr))
274        __(movl rcontext(tcr.save_allocptr),%allocptr)
275        __(rcmpl(%allocptr,rcontext(tcr.save_allocbase)))
276        __(ja macro_label(no_trap))
277        uuo_alloc()
278macro_label(no_trap):
279        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
280/* Easy to interrupt now that tcr.save_allocptr isn't tagged as a cons    */
281        __(movl $2,cons.cdr(%allocptr))
282        __(movl $1,cons.car(%allocptr))
283        ifelse($3,[],[],[
284         __(movl %allocptr,$3)
285        ])
286])],[
287
288define([Cons],[
289        new_macro_labels()
290/* The instructions where tcr.save_allocptr is tagged are difficult  */
291/* to interrupt; the interrupting code has to recognize and possibly  */
292/* emulate the instructions in between   */
293        __(subq $cons.size-fulltag_cons,rcontext(tcr.save_allocptr))
294        __(movq rcontext(tcr.save_allocptr),%allocptr)
295        __(rcmpq(%allocptr,rcontext(tcr.save_allocbase)))
296        __(ja macro_label(no_trap))
297        uuo_alloc()
298macro_label(no_trap):   
299        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
300/* Easy to interrupt now that tcr.save_allocptr isn't tagged as a cons    */
301        __(movq $2,cons.cdr(%allocptr))
302        __(movq $1,cons.car(%allocptr))
303        ifelse($3,[],[],[
304         __(movq %allocptr,$3)
305        ])
306])])
307
308ifdef([X8632],[
309/* Header in %mm0, size in bytes in %imm0.  We bash %imm0. */
310define([Misc_Alloc],[
311        __(sub [$]fulltag_misc,%imm0)
312        Misc_Alloc_Internal($1)
313])],[
314/* Header in %imm0, size in bytes in %imm1.  We bash %imm1. */
315define([Misc_Alloc],[
316        __(subq [$]fulltag_misc,%imm1)
317        Misc_Alloc_Internal($1)
318])])
319
320/* Here Be Monsters: we have to treat some/all of this instruction   */
321/* sequence atomically, as soon as tcr.save_allocptr becomes tagged.  */
322               
323ifdef([X8632],[
324define([Misc_Alloc_Internal],[                 
325        new_macro_labels()
326        __(subl %imm0,rcontext(tcr.save_allocptr))
327        __(movl rcontext(tcr.save_allocptr),%allocptr)
328        __(cmpl rcontext(tcr.save_allocbase),%allocptr)
329        __(ja macro_label(no_trap))
330        uuo_alloc()
331macro_label(no_trap):   
332        __(movd %mm0,misc_header_offset(%allocptr))
333        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
334/* Now that tcr.save_allocptr is untagged, it's easier to be interrupted   */
335        ifelse($1,[],[],[
336         __(mov %allocptr,$1)
337        ])
338])],[   
339define([Misc_Alloc_Internal],[                 
340        new_macro_labels()
341        __(subq %imm1,rcontext(tcr.save_allocptr))
342        __(movq rcontext(tcr.save_allocptr),%allocptr)
343        __(rcmpq(%allocptr,rcontext(tcr.save_allocbase)))
344        __(ja macro_label(no_trap))
345        uuo_alloc()
346macro_label(no_trap):   
347        __(movq %imm0,misc_header_offset(%allocptr))
348        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
349/* Now that tcr.save_allocptr is untagged, it's easier to be interrupted   */
350        ifelse($1,[],[],[
351         __(mov %allocptr,$1)
352        ])
353])])
354
355ifdef([X8632],[
356define([Misc_Alloc_Fixed],[
357        __(mov [$]$2-fulltag_misc,%imm0)
358        Misc_Alloc_Internal($1)
359])],[
360define([Misc_Alloc_Fixed],[
361        __(movq [$]$2-fulltag_misc,%imm1)
362        Misc_Alloc_Internal($1)
363])])                                   
364
365define([vrefr],[
366        __(mov misc_data_offset+($3<<word_shift)($2),$1)
367])     
368
369define([jump_fn],[
370        __(jmp *%fn)
371])
372                       
373define([jump_fname],[
374        __(mov symbol.fcell(%fname),%fn)
375        jump_fn()
376])     
377
378ifdef([X8632],[
379define([set_nargs],[
380        __(xorl %nargs,%nargs)
381        __(addl [$]$1<<fixnumshift,%nargs)
382])],[
383define([set_nargs],[
384        ifelse(eval($1>15),1,[
385        __(movl [$]$1<<fixnumshift,%nargs)
386        ],[
387        __(xorl %nargs,%nargs)
388        ifelse(eval($1),0,[],[
389        __(addl [$]$1<<fixnumshift,%nargs)
390        ])])])
391])
392
393/* $1 = ndigits.  Assumes 4-byte digits           */
394define([aligned_bignum_size],[((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))])
395       
396
397define([_car],[
398        __(mov cons.car($1),$2)
399])     
400
401define([_rplaca],[
402        __(mov $2,cons.car($1))
403])     
404               
405define([_cdr],[
406        __(mov cons.cdr($1),$2)
407])
408
409define([_rplacd],[
410        __(mov $2,cons.cdr($1))
411])     
412               
413       
414       
415ifdef([X8632],[
416define([tra],[
417        .p2align 3
418        .long 0
419        .byte 0
420$1:     
421])],[
422define([tra],[
423        .p2align 3
424        ifelse($2,[],[
425        .long 0
426        ],[
427        .long $1-$2
428        ])
429$1:     
430])])
431
432ifdef([X8632],[
433define([do_funcall],[
434        new_macro_labels()
435        extract_fulltag(%temp0,%imm0)
436        __(cmpb $fulltag_misc,%imm0_b)
437        __(jne macro_label(bad))
438        __(cmpb $subtag_function,misc_subtag_offset(%temp0))
439        __(jne macro_label(maybe_symbol))
440        __(mov %temp0,%fn)
441        __(jmp *%fn)
442macro_label(maybe_symbol):
443        __(cmpb $subtag_symbol,misc_subtag_offset(%temp0))
444        __(jne macro_label(bad))
445        /* %fname == %temp0 */
446        __(mov symbol.fcell(%fname),%fn)
447        __(jmp *%fn)
448macro_label(bad):
449        __(uuo_error_not_callable)
450])],[
451define([do_funcall],[
452        new_macro_labels()
453        __(movb %temp0_b,%imm0_b)
454        __(andb $fulltagmask,%imm0_b)
455        __(cmpb $fulltag_symbol,%imm0_b)
456        /* %fname == %temp0   */
457        __(cmovgq %temp0,%fn)
458        jl macro_label(bad)
459        __(cmoveq symbol.fcell(%fname),%fn)
460        __(jmp *%fn)
461macro_label(bad):               
462        __(uuo_error_not_callable)
463])])
464
465define([getvheader],[
466        __(mov misc_header_offset($1),$2)
467])
468
469/* "Size" is unboxed element-count.  $1 (header) and $2 (dest) should  */
470/*    both be immediate registers   */
471define([header_size],[
472        __(mov $1,$2)
473        __(shr $num_subtag_bits,$2)
474])
475
476/* $2 (length) is fixnum element-count.   */
477define([header_length],[
478        __(mov $~255,$2)
479        __(and $1,$2)
480        __(shr $num_subtag_bits-fixnumshift,$2)
481])
482
483/* $1 = vector, $2 = header, $3 = dest   */
484define([vector_size],[                                 
485        __(getvheader($1,$2))
486        __(header_size($2,$3))
487])
488
489/* $1 = vector, $2 = dest   */
490define([vector_length],[                                 
491        __(mov $~255,$2)
492        __(and misc_header_offset($1),$2)
493        __(shr $num_subtag_bits-fixnumshift,$2)
494])
495               
496/* GAS/ATT comparison arg order drives me nuts   */
497define([rcmpq],[
498        __(cmpq $2,$1)
499])
500
501define([rcmpl],[
502        __(cmpl $2,$1)
503])     
504
505define([rcmpw],[
506        __(cmpw $2,$1)
507])     
508
509define([rcmpb],[
510        __(cmpb $2,$1)
511])             
512
513
514define([condition_to_boolean],[
515        __(movl [$]t_value,$2_l)
516        __(lea (-t_offset)($2),$3)
517        __(cmov$1l $2_l,$3_l)
518])
519
520ifdef([X8632],[
521define([compare_reg_to_nil],[
522        __(cmp $nil_value,$1)
523])],[
524define([compare_reg_to_nil],[
525        __(cmpb $fulltag_nil,$1_b)
526])])
527
528ifdef([X8632],[
529define([extract_lisptag],[
530        __(movl $1,$2)
531        __(and [$]tagmask,$2)
532])],[
533define([extract_lisptag],[
534        __(movzbl $1_b,$2_l)
535        __(andb [$]tagmask,$2_b)
536])])
537
538                                                               
539define([extract_fulltag],[
540        __(movzbl $1_b,$2_l)
541        __(andb [$]fulltagmask,$2_b)
542])
543
544define([extract_subtag],[
545        __(movb misc_subtag_offset($1),$2)
546])
547
548ifdef([X8632],[
549define([extract_typecode],[
550        new_macro_labels()
551        __(mov $1,$2)
552        __(andl $tagmask,$2)
553        __(cmpb $tag_misc,$2_b)
554        __(jne macro_label(done))
555        __(movb misc_subtag_offset($1),$2_b)
556macro_label(done):
557])],[
558define([extract_typecode],[
559        new_macro_labels()
560        __(movzbl $1_b,$2_l)
561        __(andb $tagmask,$2_b)
562        __(cmpb $tag_misc,$2_b)
563        __(jne macro_label(done))
564        __(movb misc_subtag_offset($1),$2_b)
565macro_label(done):
566])])
567
568/* dnode_align(src,delta,dest)  */
569
570define([dnode_align],[
571        __(lea ($2+(dnode_size-1))($1),$3)
572        __(andb $~(dnode_size-1),$3_b)
573])
574
575ifdef([X8632],[
576define([push_argregs],[
577        new_macro_labels()
578        /* xxx hack alert: when the compiler calls a keyword subprim */
579        /* (SPsimple_keywords, SPkeyword_args, SP_keyword_bind) */
580        /* it puts some flags in the upper half of %temp1, which
581        /* is %nargs.  We use the cmpw here to avoid seeing those flags. */
582        __(cmpw [$]1*node_size,%nargs_w)
583        __(jb macro_label(done))
584        __(je macro_label(z))
585        __(push %arg_y)
586macro_label(z):
587        __(push %arg_z)
588macro_label(done):
589])],[
590define([push_argregs],[
591        new_macro_labels()
592        __(testl %nargs,%nargs)
593        __(jz macro_label(done))
594        __(cmpl [$]2*node_size,%nargs)
595        __(je macro_label(yz))
596        __(jb macro_label(z))
597        __(push %arg_x)
598macro_label(yz):
599        __(push %arg_y)
600macro_label(z):
601        __(push %arg_z)
602macro_label(done):
603])])   
604
605
606/* $1 = ndigits.  Assumes 4-byte digits           */
607define([aligned_bignum_size],[((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))])
608
609define([discard_temp_frame],[
610        __(mov rcontext(tcr.save_tsp),$1)
611        __(mov ($1),$1)
612        __(mov $1,rcontext(tcr.save_tsp))
613        __(mov $1,rcontext(tcr.next_tsp))
614])
615
616ifdef([X8632],[
617define([check_pending_enabled_interrupt],[
618        __(btrl [$]31,rcontext(tcr.interrupt_pending))
619        __(jnc $1)
620        interrupt_now()
621])],[
622define([check_pending_enabled_interrupt],[
623        __(btrq [$]63,rcontext(tcr.interrupt_pending))
624        __(jnc $1)
625        interrupt_now()
626])])
627       
628/* $1 = scratch register, used to access tcr.tlb_pointer.  An interrupt  */
629/*   should be taken if interrupts are enabled and the most significant  */
630/*   bit of tcr.interrupt_pending is set.  If we take the interrupt, we  */
631/*   test and clear the pending bit.  */
632
633define([check_pending_interrupt],[
634        new_macro_labels()
635        __(mov rcontext(tcr.tlb_pointer),$1)
636        __(cmp [$]0,INTERRUPT_LEVEL_BINDING_INDEX($1))
637        __(js macro_label(done))
638        check_pending_enabled_interrupt(macro_label(done))
639macro_label(done):
640])
641
642/* This should only be called from a foreign context; it should be */
643/* assumed to bash all non-volatile C registers.  And of course it's */
644/* ugly, awful, non-portable, and slow.  %rdi should point to the */
645/* linear address that %gs should be made to address (tcr or pthread data) */
646                               
647ifdef([DARWIN_GS_HACK],[
648define([set_gs_base],[
649        ifelse($1,[],[
650        ],[
651        __(movq $1,%rdi)
652        ])
653        __(movl [$]0x3000003,%eax)
654        __(syscall)
655])
656
657/* %gs addresses the tcr.  Make it address pthread data before running */
658/* foreign code */       
659       
660define([set_foreign_gs_base],[
661        set_gs_base([rcontext(tcr.osid)])
662])
663
664/* %gs addresses the tcr.  Get the linear address of the tcr and */
665/* copy it to $1 */
666
667define([save_tcr_linear],[
668        __(movq rcontext(tcr.linear),$1)
669])
670       
671])
672
673/*  On AMD hardware (at least), a one-byte RET instruction should be */
674/*  prefixed with a REP prefix if it (a) is the target of a  */
675/*  branch or (b) immediately follows a conditional branch not taken. */
676define([repret],[
677        __(.byte 0xf3)
678        __(ret)
679])
680
681ifdef([X8632],[
682define([regnum],[ifelse($1, [%eax], [0],
683       $1, [%ecx], [1],
684       $1, [%edx], [2],
685       $1, [%ebx], [3],
686       $1, [%esp], [4],
687       $1, [%ebp], [5],
688       $1, [%esi], [6],
689       $1, [%edi], [7],
690        "unknown register")dnl
691])
692
693define([mark_as_node], [
694        __(xorl $1,$1)
695        __(orb [$](1<<regnum($1)), rcontext(tcr.node_regs_mask))
696])
697
698define([mark_as_imm],[
699        __(andb [$]~(1<<regnum($1)), rcontext(tcr.node_regs_mask))
700])
701])
702
703define([check_cstack_alignment],[
704        new_macro_labels()
705        __(testb [$]7,rcontext(tcr.foreign_sp))
706        __(je macro_label(done))
707        __(hlt)
708macro_label(done):
709])
710                       
Note: See TracBrowser for help on using the repository browser.