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