1 ! Copyright (C) 2007, 2009 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 ;
11 ! C to Factor entry point
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.
18 frame-reg stack-reg MOV
20 ! Save all non-volatile registers
23 ! Save old stack pointer and align
24 safe-reg stack-reg MOV
25 stack-reg bootstrap-cell SUB
27 stack-reg [] safe-reg MOV
29 ! Register shadow area - only required on Win64, but doesn't
30 ! hurt on other platforms
33 ! Call into Factor code
34 safe-reg 0 MOV rc-absolute-cell rt-xt jit-rel
37 ! Tear down register shadow area
40 ! Undo stack alignment
41 stack-reg stack-reg [] MOV
43 ! Restore non-volatile registers
44 nv-regs <reversed> [ POP ] each
48 ! Callbacks which return structs, or use stdcall, need a
49 ! parameter here. See the comment in callback-return-rewind
51 HEX: ffff RET rc-absolute-2 rt-untagged jit-rel
52 ] callback-stub jit-define
56 temp0 0 MOV rc-absolute-cell rt-literal jit-rel
57 ! Bump profiling counter
58 temp0 profile-count-offset [+] 1 tag-fixnum ADD
60 temp0 temp0 word-code-offset [+] MOV
62 temp0 compiled-header-size ADD
65 ] jit-profiling jit-define
69 temp0 0 MOV rc-absolute-cell rt-literal jit-rel
70 ! increment datastack pointer
71 ds-reg bootstrap-cell ADD
72 ! store literal on datastack
77 temp3 0 MOV rc-absolute-cell rt-here jit-rel
78 0 JMP rc-relative rt-xt-pic-tail jit-rel
79 ] jit-word-jump jit-define
82 0 CALL rc-relative rt-xt-pic jit-rel
83 ] jit-word-call jit-define
89 ds-reg bootstrap-cell SUB
90 ! compare boolean with f
91 temp0 \ f type-number CMP
92 ! jump to true branch if not equal
93 0 JNE rc-relative rt-xt jit-rel
94 ! jump to false branch if equal
95 0 JMP rc-relative rt-xt jit-rel
99 rs-reg bootstrap-cell ADD
101 ds-reg bootstrap-cell SUB
102 rs-reg [] temp0 MOV ;
105 rs-reg 2 bootstrap-cells ADD
107 temp1 ds-reg -1 bootstrap-cells [+] MOV
108 ds-reg 2 bootstrap-cells SUB
110 rs-reg -1 bootstrap-cells [+] temp1 MOV ;
113 rs-reg 3 bootstrap-cells ADD
115 temp1 ds-reg -1 bootstrap-cells [+] MOV
116 temp2 ds-reg -2 bootstrap-cells [+] MOV
117 ds-reg 3 bootstrap-cells SUB
119 rs-reg -1 bootstrap-cells [+] temp1 MOV
120 rs-reg -2 bootstrap-cells [+] temp2 MOV ;
123 ds-reg bootstrap-cell ADD
125 rs-reg bootstrap-cell SUB
126 ds-reg [] temp0 MOV ;
129 ds-reg 2 bootstrap-cells ADD
131 temp1 rs-reg -1 bootstrap-cells [+] MOV
132 rs-reg 2 bootstrap-cells SUB
134 ds-reg -1 bootstrap-cells [+] temp1 MOV ;
137 ds-reg 3 bootstrap-cells ADD
139 temp1 rs-reg -1 bootstrap-cells [+] MOV
140 temp2 rs-reg -2 bootstrap-cells [+] MOV
141 rs-reg 3 bootstrap-cells SUB
143 ds-reg -1 bootstrap-cells [+] temp1 MOV
144 ds-reg -2 bootstrap-cells [+] temp2 MOV ;
148 0 CALL rc-relative rt-xt jit-rel
154 0 CALL rc-relative rt-xt jit-rel
156 ] jit-2dip jit-define
160 0 CALL rc-relative rt-xt jit-rel
162 ] jit-3dip jit-define
168 ds-reg bootstrap-cell SUB
170 [ temp0 word-xt-offset [+] CALL ]
171 [ temp0 word-xt-offset [+] JMP ]
172 \ (execute) define-sub-primitive*
176 ds-reg bootstrap-cell SUB
177 temp0 word-xt-offset [+] JMP
178 ] jit-execute jit-define
181 stack-reg stack-frame-size bootstrap-cell - ADD
182 ] jit-epilog jit-define
184 [ 0 RET ] jit-return jit-define
186 ! ! ! Polymorphic inline caches
188 ! The PIC stubs are not permitted to touch temp3.
190 ! Load a value from a stack position
192 temp1 ds-reg HEX: ffffffff [+] MOV rc-absolute rt-untagged jit-rel
193 ] pic-load jit-define
197 temp1 tag-mask get AND
198 temp1 tag-bits get SHL ;
200 [ load-tag ] pic-tag jit-define
202 ! The 'make' trick lets us compute the jump distance for the
203 ! conditional branches there
209 temp1 tuple type-number tag-fixnum CMP
211 [ temp1 temp0 tuple type-number neg bootstrap-cell + [+] MOV ]
213 ] pic-tuple jit-define
216 temp1 HEX: ffffffff CMP rc-absolute rt-literal jit-rel
217 ] pic-check-tag jit-define
220 temp2 HEX: ffffffff MOV rc-absolute-cell rt-literal jit-rel
222 ] pic-check-tuple jit-define
224 [ 0 JE rc-relative rt-xt jit-rel ] pic-hit jit-define
226 ! ! ! Megamorphic caches
230 temp0 0 MOV rc-absolute-cell rt-literal jit-rel
231 ! key = hashcode(class)
233 bootstrap-cell 4 = [ temp2 1 SHR ] when
234 ! key &= cache.length - 1
235 temp2 mega-cache-size get 1 - bootstrap-cell * AND
236 ! cache += array-start-offset
237 temp0 array-start-offset ADD
240 ! if(get(cache) == class)
242 bootstrap-cell 4 = 14 22 ? JNE ! Yuck!
243 ! megamorphic_cache_hits++
244 temp1 0 MOV rc-absolute-cell rt-megamorphic-cache-hits jit-rel
246 ! goto get(cache + bootstrap-cell)
247 temp0 temp0 bootstrap-cell [+] MOV
248 temp0 word-xt-offset [+] JMP
249 ! fall-through on miss
250 ] mega-lookup jit-define
259 temp0 tag-mask get AND
261 temp0 tag-bits get SHL
264 ] \ tag define-sub-primitive
269 ! adjust stack pointer
270 ds-reg bootstrap-cell SUB
273 ! turn slot number into offset
276 temp1 tag-bits get SHR
277 temp1 tag-bits get SHL
279 temp0 temp1 temp0 [+] MOV
282 ] \ slot define-sub-primitive
286 ds-reg bootstrap-cell SUB
287 ] \ drop define-sub-primitive
290 ds-reg 2 bootstrap-cells SUB
291 ] \ 2drop define-sub-primitive
294 ds-reg 3 bootstrap-cells SUB
295 ] \ 3drop define-sub-primitive
299 ds-reg bootstrap-cell ADD
301 ] \ dup define-sub-primitive
305 temp1 ds-reg bootstrap-cell neg [+] MOV
306 ds-reg 2 bootstrap-cells ADD
308 ds-reg bootstrap-cell neg [+] temp1 MOV
309 ] \ 2dup define-sub-primitive
313 temp1 ds-reg -1 bootstrap-cells [+] MOV
314 temp3 ds-reg -2 bootstrap-cells [+] MOV
315 ds-reg 3 bootstrap-cells ADD
317 ds-reg -1 bootstrap-cells [+] temp1 MOV
318 ds-reg -2 bootstrap-cells [+] temp3 MOV
319 ] \ 3dup define-sub-primitive
323 ds-reg bootstrap-cell SUB
325 ] \ nip define-sub-primitive
329 ds-reg 2 bootstrap-cells SUB
331 ] \ 2nip define-sub-primitive
334 temp0 ds-reg -1 bootstrap-cells [+] MOV
335 ds-reg bootstrap-cell ADD
337 ] \ over define-sub-primitive
340 temp0 ds-reg -2 bootstrap-cells [+] MOV
341 ds-reg bootstrap-cell ADD
343 ] \ pick define-sub-primitive
347 temp1 ds-reg -1 bootstrap-cells [+] MOV
349 ds-reg bootstrap-cell ADD
351 ] \ dupd define-sub-primitive
355 temp1 ds-reg bootstrap-cell neg [+] MOV
356 ds-reg bootstrap-cell neg [+] temp0 MOV
358 ] \ swap define-sub-primitive
361 temp0 ds-reg -1 bootstrap-cells [+] MOV
362 temp1 ds-reg -2 bootstrap-cells [+] MOV
363 ds-reg -2 bootstrap-cells [+] temp0 MOV
364 ds-reg -1 bootstrap-cells [+] temp1 MOV
365 ] \ swapd define-sub-primitive
369 temp1 ds-reg -1 bootstrap-cells [+] MOV
370 temp3 ds-reg -2 bootstrap-cells [+] MOV
371 ds-reg -2 bootstrap-cells [+] temp1 MOV
372 ds-reg -1 bootstrap-cells [+] temp0 MOV
374 ] \ rot define-sub-primitive
378 temp1 ds-reg -1 bootstrap-cells [+] MOV
379 temp3 ds-reg -2 bootstrap-cells [+] MOV
380 ds-reg -2 bootstrap-cells [+] temp0 MOV
381 ds-reg -1 bootstrap-cells [+] temp3 MOV
383 ] \ -rot define-sub-primitive
385 [ jit->r ] \ load-local define-sub-primitive
388 : jit-compare ( insn -- )
391 temp3 0 MOV rc-absolute-cell rt-literal jit-rel
393 temp1 \ f type-number MOV
396 ! adjust stack pointer
397 ds-reg bootstrap-cell SUB
398 ! compare with second value
401 [ temp1 temp3 ] dip execute( dst src -- )
403 ds-reg [] temp1 MOV ;
405 : define-jit-compare ( insn word -- )
406 [ [ jit-compare ] curry ] dip define-sub-primitive ;
408 \ CMOVE \ eq? define-jit-compare
409 \ CMOVGE \ fixnum>= define-jit-compare
410 \ CMOVLE \ fixnum<= define-jit-compare
411 \ CMOVG \ fixnum> define-jit-compare
412 \ CMOVL \ fixnum< define-jit-compare
415 : jit-math ( insn -- )
419 ds-reg bootstrap-cell SUB
421 [ ds-reg [] temp0 ] dip execute( dst src -- ) ;
423 [ \ ADD jit-math ] \ fixnum+fast define-sub-primitive
425 [ \ SUB jit-math ] \ fixnum-fast define-sub-primitive
431 ds-reg bootstrap-cell SUB
435 temp0 tag-bits get SAR
440 ] \ fixnum*fast define-sub-primitive
442 [ \ AND jit-math ] \ fixnum-bitand define-sub-primitive
444 [ \ OR jit-math ] \ fixnum-bitor define-sub-primitive
446 [ \ XOR jit-math ] \ fixnum-bitxor define-sub-primitive
452 ds-reg [] tag-mask get XOR
453 ] \ fixnum-bitnot define-sub-primitive
457 shift-arg ds-reg [] MOV
459 shift-arg tag-bits get SAR
460 ! adjust stack pointer
461 ds-reg bootstrap-cell SUB
466 ! compute positive shift value in temp1
469 ! compute negative shift value in temp3
471 temp3 tag-mask get bitnot AND
473 ! if shift count was negative, move temp0 to temp1
477 ] \ fixnum-shift-fast define-sub-primitive
479 : jit-fixnum-/mod ( -- )
480 ! load second parameter
482 ! load first parameter
483 div-arg ds-reg bootstrap-cell neg [+] MOV
487 mod-arg bootstrap-cell-bits 1 - SAR
493 ! adjust stack pointer
494 ds-reg bootstrap-cell SUB
496 ds-reg [] mod-arg MOV
497 ] \ fixnum-mod define-sub-primitive
501 ! adjust stack pointer
502 ds-reg bootstrap-cell SUB
504 div-arg tag-bits get SHL
506 ds-reg [] div-arg MOV
507 ] \ fixnum/i-fast define-sub-primitive
512 div-arg tag-bits get SHL
514 ds-reg [] mod-arg MOV
515 ds-reg bootstrap-cell neg [+] div-arg MOV
516 ] \ fixnum/mod-fast define-sub-primitive
520 ds-reg bootstrap-cell SUB
522 temp0 tag-mask get AND
523 temp0 \ f type-number MOV
524 temp1 1 tag-fixnum MOV
527 ] \ both-fixnums? define-sub-primitive
532 ! turn local number into offset
535 temp0 rs-reg temp0 [+] MOV
538 ] \ get-local define-sub-primitive
543 ! adjust stack pointer
544 ds-reg bootstrap-cell SUB
545 ! turn local number into offset
547 ! decrement retain stack pointer
549 ] \ drop-locals define-sub-primitive
551 [ "bootstrap.x86" forget-vocab ] with-compilation-unit