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