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