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