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