]> gitweb.factorcode.org Git - factor.git/blobdiff - basis/cpu/x86/bootstrap.factor
use radix literals
[factor.git] / basis / cpu / x86 / bootstrap.factor
index ab02ce7e74618886298c837c224838bd4ca4718e..3c6d7ae8de60449f3cefe90b72e4eaaae5eafa89 100644 (file)
-! Copyright (C) 2007, 2009 Slava Pestov.
+! Copyright (C) 2007, 2011 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: bootstrap.image.private compiler.constants
-compiler.units cpu.x86.assembler cpu.x86.assembler.operands
-kernel kernel.private layouts locals.backend make math
-math.private namespaces sequences slots.private vocabs ;
+compiler.codegen.relocation compiler.units cpu.x86.assembler
+cpu.x86.assembler.operands kernel kernel.private layouts
+locals locals.backend make math math.private namespaces sequences
+slots.private strings.private vocabs ;
 IN: bootstrap.x86
 
 big-endian off
 
+! C to Factor entry point
 [
-    ! Load word
-    temp0 0 MOV rc-absolute-cell rt-immediate jit-rel
-    ! Bump profiling counter
-    temp0 profile-count-offset [+] 1 tag-fixnum ADD
-    ! Load word->code
-    temp0 temp0 word-code-offset [+] MOV
-    ! Compute word XT
-    temp0 compiled-header-size ADD
-    ! Jump to XT
-    temp0 JMP
-] jit-profiling jit-define
+    ! Optimizing compiler's side of callback accesses
+    ! arguments that are on the stack via the frame pointer.
+    ! On x86-32 fastcall, and x86-64, some arguments are passed
+    ! in registers, and so the only registers that are safe for
+    ! use here are frame-reg, nv-reg and vm-reg.
+    frame-reg PUSH
+    frame-reg stack-reg MOV
 
-[
-    ! load XT
-    temp0 0 MOV rc-absolute-cell rt-this jit-rel
-    ! save stack frame size
-    stack-frame-size PUSH
-    ! push XT
-    temp0 PUSH
-    ! alignment
-    stack-reg stack-frame-size 3 bootstrap-cells - SUB
-] jit-prolog jit-define
+    ! Save all non-volatile registers
+    nv-regs [ PUSH ] each
+
+    jit-save-tib
+
+    ! Load VM into vm-reg
+    vm-reg 0 MOV 0 rc-absolute-cell rel-vm
+
+    ! Save old context
+    nv-reg vm-reg vm-context-offset [+] MOV
+    nv-reg PUSH
+
+    ! Switch over to the spare context
+    nv-reg vm-reg vm-spare-context-offset [+] MOV
+    vm-reg vm-context-offset [+] nv-reg MOV
+
+    ! Save C callstack pointer
+    nv-reg context-callstack-save-offset [+] stack-reg MOV
+
+    ! Load Factor stack pointers
+    stack-reg nv-reg context-callstack-bottom-offset [+] MOV
+    nv-reg jit-update-tib
+    jit-install-seh
+
+    rs-reg nv-reg context-retainstack-offset [+] MOV
+    ds-reg nv-reg context-datastack-offset [+] MOV
+
+    ! Call into Factor code
+    link-reg 0 MOV f rc-absolute-cell rel-word
+    link-reg CALL
+
+    ! Load VM into vm-reg; only needed on x86-32, but doesn't
+    ! hurt on x86-64
+    vm-reg 0 MOV 0 rc-absolute-cell rel-vm
+
+    ! Load C callstack pointer
+    nv-reg vm-reg vm-context-offset [+] MOV
+    stack-reg nv-reg context-callstack-save-offset [+] MOV
+
+    ! Load old context
+    nv-reg POP
+    vm-reg vm-context-offset [+] nv-reg MOV
+
+    ! Restore non-volatile registers
+    jit-restore-tib
+
+    nv-regs <reversed> [ POP ] each
+
+    frame-reg POP
+
+    ! Callbacks which return structs, or use stdcall/fastcall/thiscall,
+    ! need a parameter here.
+
+    ! See the comment for M\ x86.32 stack-cleanup in cpu.x86.32
+    0xffff RET f rc-absolute-2 rel-untagged
+] callback-stub jit-define
 
 [
     ! load literal
-    temp0 0 MOV rc-absolute-cell rt-immediate jit-rel
+    temp0 0 MOV f rc-absolute-cell rel-literal
     ! increment datastack pointer
     ds-reg bootstrap-cell ADD
     ! store literal on datastack
     ds-reg [] temp0 MOV
-] jit-push-immediate jit-define
+] jit-push jit-define
 
 [
-    temp3 0 MOV rc-absolute-cell rt-here jit-rel
-    0 JMP rc-relative rt-xt-pic-tail jit-rel
-] jit-word-jump jit-define
-
-[
-    0 CALL rc-relative rt-xt-pic jit-rel
+    0 CALL f rc-relative rel-word-pic
 ] jit-word-call jit-define
 
-[
-    0 JMP rc-relative rt-xt jit-rel
-] jit-word-special jit-define
+! The *-signal-handler subprimitives are special-cased in vm/quotations.cpp
+! not to trigger generation of a stack frame, so they can
+! peform their own prolog/epilog preserving registers.
+
+[| |
+    jit-signal-handler-prolog :> frame-size
+    jit-save-context
+    temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
+    temp0 CALL
+    frame-size jit-signal-handler-epilog
+    0 RET
+] \ signal-handler define-sub-primitive
+
+: leaf-frame-size ( -- n ) 4 bootstrap-cells ;
+
+[| |
+    jit-signal-handler-prolog :> frame-size
+    jit-save-context
+    temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
+    temp0 CALL
+    frame-size jit-signal-handler-epilog
+    ! Pop the fake leaf frame along with our return address
+    leaf-frame-size bootstrap-cell - RET
+] \ leaf-signal-handler define-sub-primitive
+
+[| |
+    jit-signal-handler-prolog :> frame-size
+    temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
+    temp0 CALL
+    frame-size jit-signal-handler-epilog
+    red-zone-size RET
+] \ ffi-signal-handler define-sub-primitive
+
+[| |
+    jit-signal-handler-prolog :> frame-size
+    temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
+    temp0 CALL
+    frame-size jit-signal-handler-epilog
+    red-zone-size 16 bootstrap-cell - + RET
+] \ ffi-leaf-signal-handler define-sub-primitive
 
 [
     ! load boolean
@@ -62,9 +138,9 @@ big-endian off
     ! compare boolean with f
     temp0 \ f type-number CMP
     ! jump to true branch if not equal
-    0 JNE rc-relative rt-xt jit-rel
+    0 JNE f rc-relative rel-word
     ! jump to false branch if equal
-    0 JMP rc-relative rt-xt jit-rel
+    0 JMP f rc-relative rel-word
 ] jit-if jit-define
 
 : jit->r ( -- )
@@ -117,36 +193,39 @@ big-endian off
 
 [
     jit->r
-    0 CALL rc-relative rt-xt jit-rel
+    0 CALL f rc-relative rel-word
     jit-r>
 ] jit-dip jit-define
 
 [
     jit-2>r
-    0 CALL rc-relative rt-xt jit-rel
+    0 CALL f rc-relative rel-word
     jit-2r>
 ] jit-2dip jit-define
 
 [
     jit-3>r
-    0 CALL rc-relative rt-xt jit-rel
+    0 CALL f rc-relative rel-word
     jit-3r>
 ] jit-3dip jit-define
 
-: prepare-(execute) ( -- operand )
+[
     ! load from stack
     temp0 ds-reg [] MOV
     ! pop stack
     ds-reg bootstrap-cell SUB
-    ! execute word
-    temp0 word-xt-offset [+] ;
+]
+[ temp0 word-entry-point-offset [+] CALL ]
+[ temp0 word-entry-point-offset [+] JMP ]
+\ (execute) define-combinator-primitive
 
-[ prepare-(execute) JMP ] jit-execute-jump jit-define
-
-[ prepare-(execute) CALL ] jit-execute-call jit-define
+[
+    temp0 ds-reg [] MOV
+    ds-reg bootstrap-cell SUB
+    temp0 word-entry-point-offset [+] JMP
+] jit-execute jit-define
 
 [
-    ! unwind stack frame
     stack-reg stack-frame-size bootstrap-cell - ADD
 ] jit-epilog jit-define
 
@@ -154,48 +233,43 @@ big-endian off
 
 ! ! ! Polymorphic inline caches
 
-! The PIC stubs are not permitted to touch temp3.
+! The PIC stubs are not permitted to touch pic-tail-reg.
 
 ! Load a value from a stack position
 [
-    temp1 ds-reg HEX: ffffffff [+] MOV rc-absolute rt-untagged jit-rel
+    temp1 ds-reg 0x7f [+] MOV f rc-absolute-1 rel-untagged
 ] pic-load jit-define
 
-! Tag
-: load-tag ( -- )
-    temp1 tag-mask get AND
-    temp1 tag-bits get SHL ;
-
-[ load-tag ] pic-tag jit-define
-
-! The 'make' trick lets us compute the jump distance for the
-! conditional branches there
+[ temp1 tag-mask get AND ] pic-tag jit-define
 
-! Tuple
 [
     temp0 temp1 MOV
-    load-tag
-    temp1 tuple type-number tag-fixnum CMP
-    [ temp1 temp0 tuple type-number neg bootstrap-cell + [+] MOV ] { } make
-    [ length JNE ] [ % ] bi
+    temp1 tag-mask get AND
+    temp1 tuple type-number CMP
+    [ JNE ]
+    [ temp1 temp0 tuple-class-offset [+] MOV ]
+    jit-conditional
 ] pic-tuple jit-define
 
 [
-    temp1 HEX: ffffffff CMP rc-absolute rt-immediate jit-rel
+    temp1 0x7f CMP f rc-absolute-1 rel-untagged
 ] pic-check-tag jit-define
 
-[
-    temp2 HEX: ffffffff MOV rc-absolute-cell rt-immediate jit-rel
-    temp1 temp2 CMP
-] pic-check-tuple jit-define
-
-[ 0 JE rc-relative rt-xt jit-rel ] pic-hit jit-define
+[ 0 JE f rc-relative rel-word ] pic-hit jit-define
 
 ! ! ! Megamorphic caches
 
 [
+    ! class = ...
+    temp0 temp1 MOV
+    temp1 tag-mask get AND
+    temp1 tag-bits get SHL
+    temp1 tuple type-number tag-fixnum CMP
+    [ JNE ]
+    [ temp1 temp0 tuple-class-offset [+] MOV ]
+    jit-conditional
     ! cache = ...
-    temp0 0 MOV rc-absolute-cell rt-immediate jit-rel
+    temp0 0 MOV f rc-absolute-cell rel-literal
     ! key = hashcode(class)
     temp2 temp1 MOV
     bootstrap-cell 4 = [ temp2 1 SHR ] when
@@ -207,35 +281,20 @@ big-endian off
     temp0 temp2 ADD
     ! if(get(cache) == class)
     temp0 [] temp1 CMP
-    bootstrap-cell 4 = 14 22 ? JNE ! Yuck!
-    ! megamorphic_cache_hits++
-    temp1 0 MOV rc-absolute-cell rt-megamorphic-cache-hits jit-rel
-    temp1 [] 1 ADD
-    ! goto get(cache + bootstrap-cell)
-    temp0 temp0 bootstrap-cell [+] MOV
-    temp0 word-xt-offset [+] JMP
-    ! fall-through on miss
+    [ JNE ]
+    [
+        ! megamorphic_cache_hits++
+        temp1 0 MOV rc-absolute-cell rel-megamorphic-cache-hits
+        temp1 [] 1 ADD
+        ! goto get(cache + bootstrap-cell)
+        temp0 temp0 bootstrap-cell [+] MOV
+        temp0 word-entry-point-offset [+] JMP
+        ! fall-through on miss
+    ] jit-conditional
 ] mega-lookup jit-define
 
-[
-    safe-reg 0 MOV rc-absolute-cell rt-xt jit-rel
-    safe-reg JMP
-] callback-stub jit-define
-
 ! ! ! Sub-primitives
 
-! Quotations and words
-[
-    ! load from stack
-    arg1 ds-reg [] MOV
-    ! pop stack
-    ds-reg bootstrap-cell SUB
-    ! pass vm pointer
-    arg2 0 MOV 0 jit-parameter rc-absolute-cell rt-vm jit-rel
-    ! call quotation
-    arg1 quot-xt-offset [+] JMP
-] \ (call) define-sub-primitive
-
 ! Objects
 [
     ! load from stack
@@ -266,6 +325,21 @@ big-endian off
     ds-reg [] temp0 MOV
 ] \ slot define-sub-primitive
 
+[
+    ! load string index from stack
+    temp0 ds-reg bootstrap-cell neg [+] MOV
+    temp0 tag-bits get SHR
+    ! load string from stack
+    temp1 ds-reg [] MOV
+    ! load character
+    temp0 8-bit-version-of temp0 temp1 string-offset [++] MOV
+    temp0 temp0 8-bit-version-of MOVZX
+    temp0 tag-bits get SHL
+    ! store character to stack
+    ds-reg bootstrap-cell SUB
+    ds-reg [] temp0 MOV
+] \ string-nth-fast define-sub-primitive
+
 ! Shufflers
 [
     ds-reg bootstrap-cell SUB
@@ -372,8 +446,7 @@ big-endian off
 ! Comparisons
 : jit-compare ( insn -- )
     ! load t
-    t jit-literal
-    temp3 0 MOV rc-absolute-cell rt-immediate jit-rel
+    temp3 0 MOV t rc-absolute-cell rel-literal
     ! load f
     temp1 \ f type-number MOV
     ! load first value
@@ -421,7 +494,7 @@ big-endian off
     ! multiply
     temp0 temp1 IMUL2
     ! push result
-    ds-reg [] temp1 MOV
+    ds-reg [] temp0 MOV
 ] \ fixnum*fast define-sub-primitive
 
 [ \ AND jit-math ] \ fixnum-bitand define-sub-primitive
@@ -447,23 +520,23 @@ big-endian off
     ! load value
     temp3 ds-reg [] MOV
     ! make a copy
-    temp1 temp3 MOV
-    ! compute positive shift value in temp1
-    temp1 CL SHL
+    temp2 temp3 MOV
+    ! compute positive shift value in temp2
+    temp2 CL SHL
     shift-arg NEG
     ! compute negative shift value in temp3
     temp3 CL SAR
     temp3 tag-mask get bitnot AND
     shift-arg 0 CMP
-    ! if shift count was negative, move temp0 to temp1
-    temp1 temp3 CMOVGE
+    ! if shift count was negative, move temp0 to temp2
+    temp2 temp3 CMOVGE
     ! push to stack
-    ds-reg [] temp1 MOV
+    ds-reg [] temp2 MOV
 ] \ fixnum-shift-fast define-sub-primitive
 
 : jit-fixnum-/mod ( -- )
     ! load second parameter
-    temp3 ds-reg [] MOV
+    temp1 ds-reg [] MOV
     ! load first parameter
     div-arg ds-reg bootstrap-cell neg [+] MOV
     ! make a copy
@@ -471,7 +544,7 @@ big-endian off
     ! sign-extend
     mod-arg bootstrap-cell-bits 1 - SAR
     ! divide
-    temp3 IDIV ;
+    temp1 IDIV ;
 
 [
     jit-fixnum-/mod
@@ -504,7 +577,7 @@ big-endian off
     temp0 ds-reg [] MOV
     ds-reg bootstrap-cell SUB
     temp0 ds-reg [] OR
-    temp0 tag-mask get AND
+    temp0 tag-mask get TEST
     temp0 \ f type-number MOV
     temp1 1 tag-fixnum MOV
     temp0 temp1 CMOVE