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