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

Last change on this file since 11828 was 11828, checked in by gb, 10 years ago

The cstack on windows needs to be committed a page at a time, so do
stack probes (via new macro 'windows_cstack_probe'). Use the macro
in x86-spentry32.s; not sure if it's needed on win64.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.5 KB
RevLine 
[4315]1/*   Copyright (C) 2005 Clozure Associates  */
2/*   This file is part of OpenMCL.    */
[2799]3
[4315]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.    */
[2799]9
[4315]10/*   OpenMCL is referenced in the preamble as the "LIBRARY."  */
[2799]11
[4315]12/*   The LLGPL is also available online at  */
13/*   http://opensource.franz.com/preamble.html  */
[2811]14
[4206]15
[5009]16/* Try to make macros follow GAS/ATT conventions, where source precedes  */
[4315]17/* destination.  */
[4299]18
[4206]19define([lisp_global],[lisp_globals.$1])
20                                       
[2811]21define([ref_global],[
[8242]22        __(mov lisp_global($1),$2)
[2811]23])
24
25define([set_global],[
[8242]26        __(mov $1,lisp_global($2))
[2811]27])
[2819]28
29define([ref_nrs_value],[
[8242]30        __(mov nrs.$1+symbol.vcell,$2)
[2819]31])
32       
33define([set_nrs_value],[
[8242]34        __(mov $1,nrs.$2+symbol.vcell)
[2819]35])
36                                                       
[2811]37define([unbox_fixnum],[
[8242]38        __(mov $1,$2)
39        __(sar [$]fixnumshift,$2)
[2811]40])
41
[3374]42define([box_fixnum],[
[10089]43        __(imul [$]fixnumone,$1,$2)
[3374]44])     
45
[5158]46
47/* box_fixnum, with no effect on flags */
48define([box_fixnum_no_flags],[
[10089]49        __(lea (,$1,fixnumone),$2)
[5158]50])
[2811]51
[10089]52
[4315]53/* Zero $3 bytes worth of dnodes, starting at offset $2 relative  */
54/* to the base register $1.  */
[3366]55
[4299]56
[3371]57ifdef([DarwinAssembler],[
[3368]58        .macro zero_dnodes
59        .if $2
[10089]60        ifdef([X8664],[
[8242]61        __(movapd %fpzero,$1($0))
[10089]62        ],[
63        __(movsd %fpzero,$1($0))
64        ])
[8242]65        __(zero_dnodes $0,$1+dnode_size,$2-dnode_size)
[3368]66        .endif
67        .endmacro
[3371]68],[
[3368]69        .macro zero_dnodes base,disp,nbytes
70        .ifgt \nbytes
[10089]71        ifdef([X8664],[
[8279]72        movapd %fpzero,\disp(\base)
[10089]73        ],[
74        movsd %fpzero,\disp(\base)
75        ])
[3377]76        zero_dnodes \base,"\disp+dnode_size","\nbytes-dnode_size"
[3368]77        .endif
78        .endm
79])     
80
81
[4315]82/* Allocate $1+dnode_size zeroed bytes on the tstack, using $2 as a temp  */
83/* reg.  */
[10089]84
85ifdef([X8632],[
[3366]86define([TSP_Alloc_Fixed],[
[3377]87        define([TSP_Alloc_Size],[((($1+node_size) & ~(dnode_size-1))+dnode_size)])
[10089]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)])
[8562]99        __(subq [$]TSP_Alloc_Size,rcontext(tcr.next_tsp))
100        __(movq rcontext(tcr.save_tsp),%stack_temp)
101        __(movq rcontext(tcr.next_tsp),$2)
[3368]102        zero_dnodes $2,0,TSP_Alloc_Size
[8242]103        __(movq %stack_temp,($2))
104        __(movq %rbp,tsp_frame.save_rbp($2))
[8562]105        __(movq $2,rcontext(tcr.save_tsp))
[3368]106        undefine([TSP_Alloc_Size])
[10089]107])])
[3366]108
[4315]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  */
[10089]111
112ifdef([X8632],[
[3390]113define([TSP_Alloc_Var],[
[10089]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],[
[4753]133        new_macro_labels()
[8562]134        subq $1,rcontext(tcr.next_tsp)
135        __(movq rcontext(tcr.save_tsp),%stack_temp)
136        __(movq rcontext(tcr.next_tsp),$2)
[8242]137        __(jmp macro_label(test))
[3390]138macro_label(loop):
[8242]139        __(movapd %fpzero,0($2))
140        __(addq $dnode_size,$2)
[3390]141macro_label(test):     
[8242]142        __(subq $dnode_size,$1)
143        __(jge macro_label(loop))
[8562]144        __(movq rcontext(tcr.next_tsp),$2)
[8242]145        __(movd %stack_temp,$1)
146        __(movq $1,($2))
147        __(movq %rbp,tsp_frame.save_rbp($2))
[8562]148        __(movq $2,rcontext(tcr.save_tsp))
[8242]149        __(addq $dnode_size,$2)
[10089]150])])
[3390]151       
152       
[10089]153ifdef([X8632],[
[3366]154define([Allocate_Catch_Frame],[
[10089]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],[
[3368]160        TSP_Alloc_Fixed(catch_frame.size,$1)
[8242]161        __(movq [$](catch_frame.element_count<<subtag_shift)|subtag_catch_frame,dnode_size($1))
162        __(addq [$]dnode_size+fulltag_misc,$1)
[10089]163])])
[3366]164
[4315]165/* %arg_z = tag,  %xfn = pc, $1 = mvflag          */
[10089]166
167ifdef([X8632],[
[3366]168define([Make_Catch],[
[10089]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],[
[6529]186        Allocate_Catch_Frame(%imm2)
[8562]187        __(movq rcontext(tcr.catch_top),%imm0)
188        __(movq rcontext(tcr.db_link),%imm1)
[8242]189        __(movq %arg_z,catch_frame.catch_tag(%imm2))
190        __(movq %imm0,catch_frame.link(%imm2))
191        __(movq [$]$1,catch_frame.mvflag(%imm2))
[8562]192        __(movq rcontext(tcr.xframe),%imm0)
[8242]193        __(movq %rsp,catch_frame.rsp(%imm2))
194        __(movq %rbp,catch_frame.rbp(%imm2))
[8562]195        __(movq rcontext(tcr.foreign_sp),%stack_temp)
[8242]196        __(movq %imm1,catch_frame.db_link(%imm2))
[8607]197        __ifndef([WINDOWS])
[8242]198        __(movq %save3,catch_frame._save3(%imm2))
[8607]199        __endif
[8242]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))
[8562]206        __(movq %imm2,rcontext(tcr.catch_top))
[10089]207])])   
[6529]208
[10089]209ifdef([X8632],[
[6529]210define([nMake_Catch],[
[10089]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],[
[6529]229        Allocate_Catch_Frame(%imm2)
[8562]230        __(movq rcontext(tcr.catch_top),%imm0)
231        __(movq rcontext(tcr.db_link),%imm1)
[8242]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))
[8562]237        __(movq rcontext(tcr.xframe),%imm0)
[8242]238        __(movq %rbp,catch_frame.rbp(%imm2))
[8562]239        __(movq rcontext(tcr.foreign_sp),%stack_temp)
[8242]240        __(movq %imm1,catch_frame.db_link(%imm2))
[8607]241        __ifndef([WINDOWS])
[8242]242        __(movq %save3,catch_frame._save3(%imm2))
[8607]243        __endif
[8242]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))
[8562]250        __(movq %imm2,rcontext(tcr.catch_top))
[10089]251])])   
[6529]252               
[3366]253       
[4315]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.  */
[4299]264
[4315]265/* $1=new_car,$2=new_cdr,$3=dest   */
[10089]266
267ifdef([X8632],[
[2811]268define([Cons],[
269        new_macro_labels()
[4315]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   */
[10089]273        __(subl $cons.size-fulltag_cons,rcontext(tcr.save_allocptr))
274        __(movl rcontext(tcr.save_allocptr),%allocptr)
275        __(rcmpl(%allocptr,rcontext(tcr.save_allocbase)))
[11556]276        __(ja macro_label(no_trap))
[10089]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   */
[8562]293        __(subq $cons.size-fulltag_cons,rcontext(tcr.save_allocptr))
294        __(movq rcontext(tcr.save_allocptr),%allocptr)
295        __(rcmpq(%allocptr,rcontext(tcr.save_allocbase)))
[11556]296        __(ja macro_label(no_trap))
[3231]297        uuo_alloc()
[2811]298macro_label(no_trap):   
[8562]299        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
[4315]300/* Easy to interrupt now that tcr.save_allocptr isn't tagged as a cons    */
[8242]301        __(movq $2,cons.cdr(%allocptr))
302        __(movq $1,cons.car(%allocptr))
[3341]303        ifelse($3,[],[],[
[8242]304         __(movq %allocptr,$3)
[2819]305        ])
[10089]306])])
[2811]307
[10089]308ifdef([X8632],[
309/* Header in %mm0, size in bytes in %imm0.  We bash %imm0. */
[2811]310define([Misc_Alloc],[
[10089]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],[
[8242]316        __(subq [$]fulltag_misc,%imm1)
[3915]317        Misc_Alloc_Internal($1)
[10089]318])])
[3915]319
[4315]320/* Here Be Monsters: we have to treat some/all of this instruction   */
321/* sequence atomically, as soon as tcr.save_allocptr becomes tagged.  */
[4299]322               
[10089]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)
[11556]329        __(ja macro_label(no_trap))
[10089]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],[                 
[3915]340        new_macro_labels()
[8562]341        __(subq %imm1,rcontext(tcr.save_allocptr))
342        __(movq rcontext(tcr.save_allocptr),%allocptr)
343        __(rcmpq(%allocptr,rcontext(tcr.save_allocbase)))
[11556]344        __(ja macro_label(no_trap))
[3231]345        uuo_alloc()
[2811]346macro_label(no_trap):   
[8242]347        __(movq %imm0,misc_header_offset(%allocptr))
[8562]348        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
[4315]349/* Now that tcr.save_allocptr is untagged, it's easier to be interrupted   */
[2819]350        ifelse($1,[],[],[
[8242]351         __(mov %allocptr,$1)
[2819]352        ])
[10089]353])])
354
355ifdef([X8632],[
[2811]356define([Misc_Alloc_Fixed],[
[10089]357        __(mov [$]$2-fulltag_misc,%imm0)
358        Misc_Alloc_Internal($1)
359])],[
360define([Misc_Alloc_Fixed],[
[8242]361        __(movq [$]$2-fulltag_misc,%imm1)
[3915]362        Misc_Alloc_Internal($1)
[10089]363])])                                   
[2819]364
365define([vrefr],[
[8242]366        __(mov misc_data_offset+($3<<word_shift)($2),$1)
[2819]367])     
368
[3236]369define([jump_fn],[
[10089]370        __(jmp *%fn)
[2819]371])
372                       
373define([jump_fname],[
[8242]374        __(mov symbol.fcell(%fname),%fn)
[3236]375        jump_fn()
[2819]376])     
[10089]377
378ifdef([X8632],[
[2819]379define([set_nargs],[
[10089]380        __(xorl %nargs,%nargs)
381        __(addl [$]$1<<fixnumshift,%nargs)
382])],[
383define([set_nargs],[
[8242]384        ifelse(eval($1>15),1,[
[8341]385        __(movl [$]$1<<fixnumshift,%nargs)
[8242]386        ],[
[8341]387        __(xorl %nargs,%nargs)
[8242]388        ifelse(eval($1),0,[],[
[8341]389        __(addl [$]$1<<fixnumshift,%nargs)
[8242]390        ])])])
[10089]391])
[2819]392
[4315]393/* $1 = ndigits.  Assumes 4-byte digits           */
[2819]394define([aligned_bignum_size],[((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))])
395       
[2836]396
397define([_car],[
[10089]398        __(mov cons.car($1),$2)
[2836]399])     
400
[3453]401define([_rplaca],[
[10089]402        __(mov $2,cons.car($1))
[3453]403])     
404               
[3368]405define([_cdr],[
[10089]406        __(mov cons.cdr($1),$2)
[3453]407])
408
409define([_rplacd],[
[10089]410        __(mov $2,cons.cdr($1))
[3368]411])     
[3453]412               
[3368]413       
[3453]414       
[10089]415ifdef([X8632],[
[2836]416define([tra],[
[5009]417        .p2align 3
[10089]418        .long 0
419        .byte 0
420$1:     
421])],[
422define([tra],[
423        .p2align 3
[2836]424        ifelse($2,[],[
[3390]425        .long 0
426        ],[
[2836]427        .long $1-$2
428        ])
[3390]429$1:     
[10089]430])])
431
432ifdef([X8632],[
[2836]433define([do_funcall],[
[10089]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],[
[2836]452        new_macro_labels()
[8242]453        __(movb %temp0_b,%imm0_b)
454        __(andb $fulltagmask,%imm0_b)
455        __(cmpb $fulltag_symbol,%imm0_b)
[4315]456        /* %fname == %temp0   */
[8242]457        __(cmovgq %temp0,%fn)
[3846]458        jl macro_label(bad)
[8242]459        __(cmoveq symbol.fcell(%fname),%fn)
460        __(jmp *%fn)
[3846]461macro_label(bad):               
462        __(uuo_error_not_callable)
[10089]463])])
[3334]464
465define([getvheader],[
[10089]466        __(mov misc_header_offset($1),$2)
[3334]467])
468
[4315]469/* "Size" is unboxed element-count.  $1 (header) and $2 (dest) should  */
470/*    both be immediate registers   */
[3334]471define([header_size],[
[10089]472        __(mov $1,$2)
[8242]473        __(shr $num_subtag_bits,$2)
[3334]474])
475
[4315]476/* $2 (length) is fixnum element-count.   */
[3334]477define([header_length],[
[10089]478        __(mov $~255,$2)
479        __(and $1,$2)
[8242]480        __(shr $num_subtag_bits-fixnumshift,$2)
[3334]481])
482
[4315]483/* $1 = vector, $2 = header, $3 = dest   */
[3334]484define([vector_size],[                                 
[10089]485        __(getvheader($1,$2))
486        __(header_size($2,$3))
[3334]487])
488
[4315]489/* $1 = vector, $2 = dest   */
[3334]490define([vector_length],[                                 
[10089]491        __(mov $~255,$2)
492        __(and misc_header_offset($1),$2)
[8242]493        __(shr $num_subtag_bits-fixnumshift,$2)
[3334]494])
[3341]495               
[4315]496/* GAS/ATT comparison arg order drives me nuts   */
[3368]497define([rcmpq],[
[8242]498        __(cmpq $2,$1)
[3368]499])
500
501define([rcmpl],[
[8242]502        __(cmpl $2,$1)
[3368]503])     
504
505define([rcmpw],[
[8242]506        __(cmpw $2,$1)
[3368]507])     
508
509define([rcmpb],[
[8242]510        __(cmpb $2,$1)
[3368]511])             
512
513
514define([condition_to_boolean],[
[8242]515        __(movl [$]t_value,$2_l)
516        __(lea (-t_offset)($2),$3)
517        __(cmov$1l $2_l,$3_l)
[3368]518])
[3537]519
[10089]520ifdef([X8632],[
[3537]521define([compare_reg_to_nil],[
[10089]522        __(cmp $nil_value,$1)
523])],[
524define([compare_reg_to_nil],[
[8242]525        __(cmpb $fulltag_nil,$1_b)
[10089]526])])
527
528ifdef([X8632],[
[3368]529define([extract_lisptag],[
[10089]530        __(movl $1,$2)
531        __(and [$]tagmask,$2)
532])],[
533define([extract_lisptag],[
[8242]534        __(movzbl $1_b,$2_l)
535        __(andb [$]tagmask,$2_b)
[10089]536])])
[4142]537
[3368]538                                                               
539define([extract_fulltag],[
[8242]540        __(movzbl $1_b,$2_l)
541        __(andb [$]fulltagmask,$2_b)
[3368]542])
543
544define([extract_subtag],[
[8242]545        __(movb misc_subtag_offset($1),$2)
[3453]546])
[3390]547
[10089]548ifdef([X8632],[
[3453]549define([extract_typecode],[
[3699]550        new_macro_labels()
[10089]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()
[8242]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)
[10089]565macro_label(done):
566])])
[3453]567
[4315]568/* dnode_align(src,delta,dest)  */
[4299]569
[10089]570define([dnode_align],[
[8242]571        __(lea ($2+(dnode_size-1))($1),$3)
572        __(andb $~(dnode_size-1),$3_b)
[3390]573])
[10089]574
575ifdef([X8632],[
[3453]576define([push_argregs],[
577        new_macro_labels()
[10089]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()
[8341]592        __(testl %nargs,%nargs)
[8242]593        __(jz macro_label(done))
[8341]594        __(cmpl [$]2*node_size,%nargs)
[8242]595        __(je macro_label(yz))
596        __(jb macro_label(z))
597        __(push %arg_x)
[3453]598macro_label(yz):
[8242]599        __(push %arg_y)
[3453]600macro_label(z):
[8242]601        __(push %arg_z)
[3453]602macro_label(done):
[10089]603])])   
[3459]604
605
[4315]606/* $1 = ndigits.  Assumes 4-byte digits           */
[3459]607define([aligned_bignum_size],[((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))])
[3537]608
609define([discard_temp_frame],[
[10089]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])
[4753]615
[10089]616ifdef([X8632],[
[4043]617define([check_pending_enabled_interrupt],[
[10089]618        __(btrl [$]31,rcontext(tcr.interrupt_pending))
619        __(jnc $1)
620        interrupt_now()
621])],[
622define([check_pending_enabled_interrupt],[
[8562]623        __(btrq [$]63,rcontext(tcr.interrupt_pending))
[10387]624        __(jnc $1)
[4043]625        interrupt_now()
[10089]626])])
[4043]627       
[4315]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.  */
[4299]632
[4043]633define([check_pending_interrupt],[
634        new_macro_labels()
[10089]635        __(mov rcontext(tcr.tlb_pointer),$1)
636        __(cmp [$]0,INTERRUPT_LEVEL_BINDING_INDEX($1))
637        __(js macro_label(done))
[4043]638        check_pending_enabled_interrupt(macro_label(done))
639macro_label(done):
640])
[4982]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        ],[
[8242]651        __(movq $1,%rdi)
[4982]652        ])
[8242]653        __(movl [$]0x3000003,%eax)
654        __(syscall)
[4982]655])
656
657/* %gs addresses the tcr.  Make it address pthread data before running */
658/* foreign code */       
659       
660define([set_foreign_gs_base],[
[8562]661        set_gs_base([rcontext(tcr.osid)])
[4982]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],[
[8562]668        __(movq rcontext(tcr.linear),$1)
[4982]669])
670       
671])
672
[6529]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],[
[8242]677        __(.byte 0xf3)
678        __(ret)
[6529]679])
[10089]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
[10499]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])
[11828]710
711        __ifdef([WINDOWS])
712define([windows_cstack_probe],[
713        new_macro_labels()
714        __(cmpl [$]0x1000,$1)
715        __(jb macro_label(done))
716        __(movl rcontext(tcr.foreign_sp),$2)
717        __(orl [$]0,-0x1000($2))
718        __(cmpl [$]0x2000,$1)
719        __(jb macro_label(done))
720        __(orl [$]0,-0x2000($2))
721        __(cmpl [$]0x3000,$1)
722        __(jb macro_label(done))
723        __(orl [$]0,-0x3000($2))
724        __(cmpl [$]0x4000,$1)
725        __(jb macro_label(done))
726        __(orl [$]0,-0x4000($2))
727        __(cmpl [$]0x5000,$1)
728        __(jb macro_label(done))
729        __(orl [$]0,-0x5000($2))
730        __(cmpl [$]0x6000,$1)
731        __(jb macro_label(done))
732        __(orl [$]0,-0x6000($2))
733        __(cmpl [$]0x7000,$1)
734        __(jb macro_label(done))
735        __(orl [$]0,-0x7000($2))
736        __(cmpl [$]0x8000,$1)
737        __(jb macro_label(done))
738        __(orl [$]0,-0x8000($2))
739        __(cmpl [$]0x9000,$1)
740        __(jb macro_label(done))
741        __(orl [$]0,-0x9000($2))
742        __(cmpl [$]0xa000,$1)
743        __(jb macro_label(done))
744        __(orl [$]0,-0xa000($2))
745        __(cmpl [$]0xb000,$1)
746        __(jb macro_label(done))
747        __(orl [$]0,-0xb000($2))
748        __(cmpl [$]0xc000,$1)
749        __(jb macro_label(done))
750        __(orl [$]0,-0xc000($2))
751        __(cmpl [$]0xd000,$1)
752        __(jb macro_label(done))
753        __(orl [$]0,-0xd000($2))
754        __(cmpl [$]0xe000,$1)
755        __(jb macro_label(done))
756        __(orl [$]0,-0xe000($2))
757        __(cmpl [$]0xf000,$1)
758        __(jb macro_label(done))
759        __(orl [$]0,-0xf000($2))
760macro_label(done):     
761])
762
763
764        __endif               
[10499]765                       
Note: See TracBrowser for help on using the repository browser.