]> gitweb.factorcode.org Git - factor.git/blob - basis/cpu/x86/bootstrap.factor
fix platform dependency in leaf-signal-handler
[factor.git] / basis / cpu / x86 / bootstrap.factor
1 ! Copyright (C) 2007, 2011 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: bootstrap.image.private compiler.constants
4 compiler.codegen.relocation compiler.units cpu.x86.assembler
5 cpu.x86.assembler.operands kernel kernel.private layouts
6 locals locals.backend make math math.private namespaces sequences
7 slots.private strings.private vocabs ;
8 IN: bootstrap.x86
9
10 big-endian off
11
12 ! C to Factor entry point
13 [
14     ! Optimizing compiler's side of callback accesses
15     ! arguments that are on the stack via the frame pointer.
16     ! On x86-32 fastcall, and x86-64, some arguments are passed
17     ! in registers, and so the only registers that are safe for
18     ! use here are frame-reg, nv-reg and vm-reg.
19     frame-reg PUSH
20     frame-reg stack-reg MOV
21
22     ! Save all non-volatile registers
23     nv-regs [ PUSH ] each
24
25     jit-save-tib
26
27     ! Load VM into vm-reg
28     vm-reg 0 MOV 0 rc-absolute-cell rel-vm
29
30     ! Save old context
31     nv-reg vm-reg vm-context-offset [+] MOV
32     nv-reg PUSH
33
34     ! Switch over to the spare context
35     nv-reg vm-reg vm-spare-context-offset [+] MOV
36     vm-reg vm-context-offset [+] nv-reg MOV
37
38     ! Save C callstack pointer
39     nv-reg context-callstack-save-offset [+] stack-reg MOV
40
41     ! Load Factor stack pointers
42     stack-reg nv-reg context-callstack-bottom-offset [+] MOV
43     nv-reg jit-update-tib
44     jit-install-seh
45
46     rs-reg nv-reg context-retainstack-offset [+] MOV
47     ds-reg nv-reg context-datastack-offset [+] MOV
48
49     ! Call into Factor code
50     link-reg 0 MOV f rc-absolute-cell rel-word
51     link-reg CALL
52
53     ! Load VM into vm-reg; only needed on x86-32, but doesn't
54     ! hurt on x86-64
55     vm-reg 0 MOV 0 rc-absolute-cell rel-vm
56
57     ! Load C callstack pointer
58     nv-reg vm-reg vm-context-offset [+] MOV
59     stack-reg nv-reg context-callstack-save-offset [+] MOV
60
61     ! Load old context
62     nv-reg POP
63     vm-reg vm-context-offset [+] nv-reg MOV
64
65     ! Restore non-volatile registers
66     jit-restore-tib
67
68     nv-regs <reversed> [ POP ] each
69
70     frame-reg POP
71
72     ! Callbacks which return structs, or use stdcall/fastcall/thiscall,
73     ! need a parameter here.
74
75     ! See the comment for M\ x86.32 stack-cleanup in cpu.x86.32
76     HEX: ffff RET f rc-absolute-2 rel-untagged
77 ] callback-stub jit-define
78
79 [
80     ! Load word
81     temp0 0 MOV f rc-absolute-cell rel-literal
82     ! Bump profiling counter
83     temp0 profile-count-offset [+] 1 tag-fixnum ADD
84     ! Load word->code
85     temp0 temp0 word-code-offset [+] MOV
86     ! Compute word entry point
87     temp0 compiled-header-size ADD
88     ! Jump to entry point
89     temp0 JMP
90 ] jit-profiling jit-define
91
92 [
93     ! load literal
94     temp0 0 MOV f rc-absolute-cell rel-literal
95     ! increment datastack pointer
96     ds-reg bootstrap-cell ADD
97     ! store literal on datastack
98     ds-reg [] temp0 MOV
99 ] jit-push jit-define
100
101 [
102     0 CALL f rc-relative rel-word-pic
103 ] jit-word-call jit-define
104
105 ! The signal-handler and leaf-signal-handler subprimitives are special-cased
106 ! in vm/quotations.cpp not to trigger generation of a stack frame, so they can
107 ! peform their own prolog/epilog preserving registers.
108
109 [| |
110     jit-signal-handler-prolog :> frame-size
111     jit-save-context
112     temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
113     temp0 CALL
114     frame-size jit-signal-handler-epilog
115 ] \ signal-handler define-sub-primitive
116
117 : leaf-frame-size ( -- n ) 4 bootstrap-cells ;
118
119 [| |
120     jit-signal-handler-prolog :> frame-size
121     jit-save-context
122     temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
123     temp0 CALL
124     frame-size jit-signal-handler-epilog
125     ! Pop the fake leaf frame along with our return address
126     leaf-frame-size cell - RET
127 ] \ leaf-signal-handler define-sub-primitive
128
129 [
130     ! load boolean
131     temp0 ds-reg [] MOV
132     ! pop boolean
133     ds-reg bootstrap-cell SUB
134     ! compare boolean with f
135     temp0 \ f type-number CMP
136     ! jump to true branch if not equal
137     0 JNE f rc-relative rel-word
138     ! jump to false branch if equal
139     0 JMP f rc-relative rel-word
140 ] jit-if jit-define
141
142 : jit->r ( -- )
143     rs-reg bootstrap-cell ADD
144     temp0 ds-reg [] MOV
145     ds-reg bootstrap-cell SUB
146     rs-reg [] temp0 MOV ;
147
148 : jit-2>r ( -- )
149     rs-reg 2 bootstrap-cells ADD
150     temp0 ds-reg [] MOV
151     temp1 ds-reg -1 bootstrap-cells [+] MOV
152     ds-reg 2 bootstrap-cells SUB
153     rs-reg [] temp0 MOV
154     rs-reg -1 bootstrap-cells [+] temp1 MOV ;
155
156 : jit-3>r ( -- )
157     rs-reg 3 bootstrap-cells ADD
158     temp0 ds-reg [] MOV
159     temp1 ds-reg -1 bootstrap-cells [+] MOV
160     temp2 ds-reg -2 bootstrap-cells [+] MOV
161     ds-reg 3 bootstrap-cells SUB
162     rs-reg [] temp0 MOV
163     rs-reg -1 bootstrap-cells [+] temp1 MOV
164     rs-reg -2 bootstrap-cells [+] temp2 MOV ;
165
166 : jit-r> ( -- )
167     ds-reg bootstrap-cell ADD
168     temp0 rs-reg [] MOV
169     rs-reg bootstrap-cell SUB
170     ds-reg [] temp0 MOV ;
171
172 : jit-2r> ( -- )
173     ds-reg 2 bootstrap-cells ADD
174     temp0 rs-reg [] MOV
175     temp1 rs-reg -1 bootstrap-cells [+] MOV
176     rs-reg 2 bootstrap-cells SUB
177     ds-reg [] temp0 MOV
178     ds-reg -1 bootstrap-cells [+] temp1 MOV ;
179
180 : jit-3r> ( -- )
181     ds-reg 3 bootstrap-cells ADD
182     temp0 rs-reg [] MOV
183     temp1 rs-reg -1 bootstrap-cells [+] MOV
184     temp2 rs-reg -2 bootstrap-cells [+] MOV
185     rs-reg 3 bootstrap-cells SUB
186     ds-reg [] temp0 MOV
187     ds-reg -1 bootstrap-cells [+] temp1 MOV
188     ds-reg -2 bootstrap-cells [+] temp2 MOV ;
189
190 [
191     jit->r
192     0 CALL f rc-relative rel-word
193     jit-r>
194 ] jit-dip jit-define
195
196 [
197     jit-2>r
198     0 CALL f rc-relative rel-word
199     jit-2r>
200 ] jit-2dip jit-define
201
202 [
203     jit-3>r
204     0 CALL f rc-relative rel-word
205     jit-3r>
206 ] jit-3dip jit-define
207
208 [
209     ! load from stack
210     temp0 ds-reg [] MOV
211     ! pop stack
212     ds-reg bootstrap-cell SUB
213 ]
214 [ temp0 word-entry-point-offset [+] CALL ]
215 [ temp0 word-entry-point-offset [+] JMP ]
216 \ (execute) define-combinator-primitive
217
218 [
219     temp0 ds-reg [] MOV
220     ds-reg bootstrap-cell SUB
221     temp0 word-entry-point-offset [+] JMP
222 ] jit-execute jit-define
223
224 [
225     jit-safepoint
226     stack-reg stack-frame-size bootstrap-cell - ADD
227 ] jit-epilog jit-define
228
229 [ 0 RET ] jit-return jit-define
230
231 ! ! ! Polymorphic inline caches
232
233 ! The PIC stubs are not permitted to touch pic-tail-reg.
234
235 ! Load a value from a stack position
236 [
237     temp1 ds-reg HEX: 7f [+] MOV f rc-absolute-1 rel-untagged
238 ] pic-load jit-define
239
240 [ temp1 tag-mask get AND ] pic-tag jit-define
241
242 [
243     temp0 temp1 MOV
244     temp1 tag-mask get AND
245     temp1 tuple type-number CMP
246     [ JNE ]
247     [ temp1 temp0 tuple-class-offset [+] MOV ]
248     jit-conditional
249 ] pic-tuple jit-define
250
251 [
252     temp1 HEX: 7f CMP f rc-absolute-1 rel-untagged
253 ] pic-check-tag jit-define
254
255 [ 0 JE f rc-relative rel-word ] pic-hit jit-define
256
257 ! ! ! Megamorphic caches
258
259 [
260     ! class = ...
261     temp0 temp1 MOV
262     temp1 tag-mask get AND
263     temp1 tag-bits get SHL
264     temp1 tuple type-number tag-fixnum CMP
265     [ JNE ]
266     [ temp1 temp0 tuple-class-offset [+] MOV ]
267     jit-conditional
268     ! cache = ...
269     temp0 0 MOV f rc-absolute-cell rel-literal
270     ! key = hashcode(class)
271     temp2 temp1 MOV
272     bootstrap-cell 4 = [ temp2 1 SHR ] when
273     ! key &= cache.length - 1
274     temp2 mega-cache-size get 1 - bootstrap-cell * AND
275     ! cache += array-start-offset
276     temp0 array-start-offset ADD
277     ! cache += key
278     temp0 temp2 ADD
279     ! if(get(cache) == class)
280     temp0 [] temp1 CMP
281     [ JNE ]
282     [
283         ! megamorphic_cache_hits++
284         temp1 0 MOV rc-absolute-cell rel-megamorphic-cache-hits
285         temp1 [] 1 ADD
286         ! goto get(cache + bootstrap-cell)
287         temp0 temp0 bootstrap-cell [+] MOV
288         temp0 word-entry-point-offset [+] JMP
289         ! fall-through on miss
290     ] jit-conditional
291 ] mega-lookup jit-define
292
293 ! ! ! Sub-primitives
294
295 ! Objects
296 [
297     ! load from stack
298     temp0 ds-reg [] MOV
299     ! compute tag
300     temp0 tag-mask get AND
301     ! tag the tag
302     temp0 tag-bits get SHL
303     ! push to stack
304     ds-reg [] temp0 MOV
305 ] \ tag define-sub-primitive
306
307 [
308     ! load slot number
309     temp0 ds-reg [] MOV
310     ! adjust stack pointer
311     ds-reg bootstrap-cell SUB
312     ! load object
313     temp1 ds-reg [] MOV
314     ! turn slot number into offset
315     fixnum>slot@
316     ! mask off tag
317     temp1 tag-bits get SHR
318     temp1 tag-bits get SHL
319     ! load slot value
320     temp0 temp1 temp0 [+] MOV
321     ! push to stack
322     ds-reg [] temp0 MOV
323 ] \ slot define-sub-primitive
324
325 [
326     ! load string index from stack
327     temp0 ds-reg bootstrap-cell neg [+] MOV
328     temp0 tag-bits get SHR
329     ! load string from stack
330     temp1 ds-reg [] MOV
331     ! load character
332     temp0 8-bit-version-of temp0 temp1 string-offset [++] MOV
333     temp0 temp0 8-bit-version-of MOVZX
334     temp0 tag-bits get SHL
335     ! store character to stack
336     ds-reg bootstrap-cell SUB
337     ds-reg [] temp0 MOV
338 ] \ string-nth-fast define-sub-primitive
339
340 ! Shufflers
341 [
342     ds-reg bootstrap-cell SUB
343 ] \ drop define-sub-primitive
344
345 [
346     ds-reg 2 bootstrap-cells SUB
347 ] \ 2drop define-sub-primitive
348
349 [
350     ds-reg 3 bootstrap-cells SUB
351 ] \ 3drop define-sub-primitive
352
353 [
354     temp0 ds-reg [] MOV
355     ds-reg bootstrap-cell ADD
356     ds-reg [] temp0 MOV
357 ] \ dup define-sub-primitive
358
359 [
360     temp0 ds-reg [] MOV
361     temp1 ds-reg bootstrap-cell neg [+] MOV
362     ds-reg 2 bootstrap-cells ADD
363     ds-reg [] temp0 MOV
364     ds-reg bootstrap-cell neg [+] temp1 MOV
365 ] \ 2dup define-sub-primitive
366
367 [
368     temp0 ds-reg [] MOV
369     temp1 ds-reg -1 bootstrap-cells [+] MOV
370     temp3 ds-reg -2 bootstrap-cells [+] MOV
371     ds-reg 3 bootstrap-cells ADD
372     ds-reg [] temp0 MOV
373     ds-reg -1 bootstrap-cells [+] temp1 MOV
374     ds-reg -2 bootstrap-cells [+] temp3 MOV
375 ] \ 3dup define-sub-primitive
376
377 [
378     temp0 ds-reg [] MOV
379     ds-reg bootstrap-cell SUB
380     ds-reg [] temp0 MOV
381 ] \ nip define-sub-primitive
382
383 [
384     temp0 ds-reg [] MOV
385     ds-reg 2 bootstrap-cells SUB
386     ds-reg [] temp0 MOV
387 ] \ 2nip define-sub-primitive
388
389 [
390     temp0 ds-reg -1 bootstrap-cells [+] MOV
391     ds-reg bootstrap-cell ADD
392     ds-reg [] temp0 MOV
393 ] \ over define-sub-primitive
394
395 [
396     temp0 ds-reg -2 bootstrap-cells [+] MOV
397     ds-reg bootstrap-cell ADD
398     ds-reg [] temp0 MOV
399 ] \ pick define-sub-primitive
400
401 [
402     temp0 ds-reg [] MOV
403     temp1 ds-reg -1 bootstrap-cells [+] MOV
404     ds-reg [] temp1 MOV
405     ds-reg bootstrap-cell ADD
406     ds-reg [] temp0 MOV
407 ] \ dupd define-sub-primitive
408
409 [
410     temp0 ds-reg [] MOV
411     temp1 ds-reg bootstrap-cell neg [+] MOV
412     ds-reg bootstrap-cell neg [+] temp0 MOV
413     ds-reg [] temp1 MOV
414 ] \ swap define-sub-primitive
415
416 [
417     temp0 ds-reg -1 bootstrap-cells [+] MOV
418     temp1 ds-reg -2 bootstrap-cells [+] MOV
419     ds-reg -2 bootstrap-cells [+] temp0 MOV
420     ds-reg -1 bootstrap-cells [+] temp1 MOV
421 ] \ swapd define-sub-primitive
422
423 [
424     temp0 ds-reg [] MOV
425     temp1 ds-reg -1 bootstrap-cells [+] MOV
426     temp3 ds-reg -2 bootstrap-cells [+] MOV
427     ds-reg -2 bootstrap-cells [+] temp1 MOV
428     ds-reg -1 bootstrap-cells [+] temp0 MOV
429     ds-reg [] temp3 MOV
430 ] \ rot define-sub-primitive
431
432 [
433     temp0 ds-reg [] MOV
434     temp1 ds-reg -1 bootstrap-cells [+] MOV
435     temp3 ds-reg -2 bootstrap-cells [+] MOV
436     ds-reg -2 bootstrap-cells [+] temp0 MOV
437     ds-reg -1 bootstrap-cells [+] temp3 MOV
438     ds-reg [] temp1 MOV
439 ] \ -rot define-sub-primitive
440
441 [ jit->r ] \ load-local define-sub-primitive
442
443 ! Comparisons
444 : jit-compare ( insn -- )
445     ! load t
446     temp3 0 MOV t rc-absolute-cell rel-literal
447     ! load f
448     temp1 \ f type-number MOV
449     ! load first value
450     temp0 ds-reg [] MOV
451     ! adjust stack pointer
452     ds-reg bootstrap-cell SUB
453     ! compare with second value
454     ds-reg [] temp0 CMP
455     ! move t if true
456     [ temp1 temp3 ] dip execute( dst src -- )
457     ! store
458     ds-reg [] temp1 MOV ;
459
460 : define-jit-compare ( insn word -- )
461     [ [ jit-compare ] curry ] dip define-sub-primitive ;
462
463 \ CMOVE \ eq? define-jit-compare
464 \ CMOVGE \ fixnum>= define-jit-compare
465 \ CMOVLE \ fixnum<= define-jit-compare
466 \ CMOVG \ fixnum> define-jit-compare
467 \ CMOVL \ fixnum< define-jit-compare
468
469 ! Math
470 : jit-math ( insn -- )
471     ! load second input
472     temp0 ds-reg [] MOV
473     ! pop stack
474     ds-reg bootstrap-cell SUB
475     ! compute result
476     [ ds-reg [] temp0 ] dip execute( dst src -- ) ;
477
478 [ \ ADD jit-math ] \ fixnum+fast define-sub-primitive
479
480 [ \ SUB jit-math ] \ fixnum-fast define-sub-primitive
481
482 [
483     ! load second input
484     temp0 ds-reg [] MOV
485     ! pop stack
486     ds-reg bootstrap-cell SUB
487     ! load first input
488     temp1 ds-reg [] MOV
489     ! untag second input
490     temp0 tag-bits get SAR
491     ! multiply
492     temp0 temp1 IMUL2
493     ! push result
494     ds-reg [] temp0 MOV
495 ] \ fixnum*fast define-sub-primitive
496
497 [ \ AND jit-math ] \ fixnum-bitand define-sub-primitive
498
499 [ \ OR jit-math ] \ fixnum-bitor define-sub-primitive
500
501 [ \ XOR jit-math ] \ fixnum-bitxor define-sub-primitive
502
503 [
504     ! complement
505     ds-reg [] NOT
506     ! clear tag bits
507     ds-reg [] tag-mask get XOR
508 ] \ fixnum-bitnot define-sub-primitive
509
510 [
511     ! load shift count
512     shift-arg ds-reg [] MOV
513     ! untag shift count
514     shift-arg tag-bits get SAR
515     ! adjust stack pointer
516     ds-reg bootstrap-cell SUB
517     ! load value
518     temp3 ds-reg [] MOV
519     ! make a copy
520     temp2 temp3 MOV
521     ! compute positive shift value in temp2
522     temp2 CL SHL
523     shift-arg NEG
524     ! compute negative shift value in temp3
525     temp3 CL SAR
526     temp3 tag-mask get bitnot AND
527     shift-arg 0 CMP
528     ! if shift count was negative, move temp0 to temp2
529     temp2 temp3 CMOVGE
530     ! push to stack
531     ds-reg [] temp2 MOV
532 ] \ fixnum-shift-fast define-sub-primitive
533
534 : jit-fixnum-/mod ( -- )
535     ! load second parameter
536     temp1 ds-reg [] MOV
537     ! load first parameter
538     div-arg ds-reg bootstrap-cell neg [+] MOV
539     ! make a copy
540     mod-arg div-arg MOV
541     ! sign-extend
542     mod-arg bootstrap-cell-bits 1 - SAR
543     ! divide
544     temp1 IDIV ;
545
546 [
547     jit-fixnum-/mod
548     ! adjust stack pointer
549     ds-reg bootstrap-cell SUB
550     ! push to stack
551     ds-reg [] mod-arg MOV
552 ] \ fixnum-mod define-sub-primitive
553
554 [
555     jit-fixnum-/mod
556     ! adjust stack pointer
557     ds-reg bootstrap-cell SUB
558     ! tag it
559     div-arg tag-bits get SHL
560     ! push to stack
561     ds-reg [] div-arg MOV
562 ] \ fixnum/i-fast define-sub-primitive
563
564 [
565     jit-fixnum-/mod
566     ! tag it
567     div-arg tag-bits get SHL
568     ! push to stack
569     ds-reg [] mod-arg MOV
570     ds-reg bootstrap-cell neg [+] div-arg MOV
571 ] \ fixnum/mod-fast define-sub-primitive
572
573 [
574     temp0 ds-reg [] MOV
575     ds-reg bootstrap-cell SUB
576     temp0 ds-reg [] OR
577     temp0 tag-mask get TEST
578     temp0 \ f type-number MOV
579     temp1 1 tag-fixnum MOV
580     temp0 temp1 CMOVE
581     ds-reg [] temp0 MOV
582 ] \ both-fixnums? define-sub-primitive
583
584 [
585     ! load local number
586     temp0 ds-reg [] MOV
587     ! turn local number into offset
588     fixnum>slot@
589     ! load local value
590     temp0 rs-reg temp0 [+] MOV
591     ! push to stack
592     ds-reg [] temp0 MOV
593 ] \ get-local define-sub-primitive
594
595 [
596     ! load local count
597     temp0 ds-reg [] MOV
598     ! adjust stack pointer
599     ds-reg bootstrap-cell SUB
600     ! turn local number into offset
601     fixnum>slot@
602     ! decrement retain stack pointer
603     rs-reg temp0 SUB
604 ] \ drop-locals define-sub-primitive
605
606 [ "bootstrap.x86" forget-vocab ] with-compilation-unit