factor/basis/cpu/x86/architecture/architecture.factor

196 lines
5.3 KiB
Factor
Raw Normal View History

2008-04-04 04:46:30 -04:00
! Copyright (C) 2005, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.c-types arrays cpu.x86.assembler
2008-08-12 04:31:48 -04:00
cpu.x86.assembler.private cpu.architecture kernel kernel.private
2008-10-07 21:00:38 -04:00
math memory namespaces make sequences words system
layouts combinators math.order locals compiler.constants
compiler.cfg.registers compiler.cfg.instructions
compiler.codegen.fixup ;
2007-09-20 18:09:08 -04:00
IN: cpu.x86.architecture
2008-06-08 16:32:55 -04:00
HOOK: ds-reg cpu ( -- reg )
HOOK: rs-reg cpu ( -- reg )
HOOK: stack-reg cpu ( -- reg )
2007-09-20 18:09:08 -04:00
2008-06-08 16:32:55 -04:00
: stack@ ( n -- op ) stack-reg swap [+] ;
2007-09-20 18:09:08 -04:00
2008-10-05 22:30:29 -04:00
: next-stack@ ( n -- operand )
#! nth parameter from the next stack frame. Used to box
#! input values to callbacks; the callback has its own
#! stack frame set up, and we want to read the frame
#! set up by the caller.
2008-10-06 01:20:00 -04:00
stack-frame get total-size>> + stack@ ;
2008-10-05 22:30:29 -04:00
2007-09-20 18:09:08 -04:00
: reg-stack ( n reg -- op ) swap cells neg [+] ;
2008-10-07 17:42:11 -04:00
GENERIC: loc>operand ( loc -- operand )
M: ds-loc loc>operand n>> ds-reg reg-stack ;
M: rs-loc loc>operand n>> rs-reg reg-stack ;
2007-09-20 18:09:08 -04:00
M: int-regs %save-param-reg drop >r stack@ r> MOV ;
M: int-regs %load-param-reg drop swap stack@ MOV ;
2008-04-04 04:46:30 -04:00
GENERIC: MOVSS/D ( dst src reg-class -- )
M: single-float-regs MOVSS/D drop MOVSS ;
M: double-float-regs MOVSS/D drop MOVSD ;
2007-09-20 18:09:08 -04:00
M: float-regs %save-param-reg >r >r stack@ r> r> MOVSS/D ;
M: float-regs %load-param-reg >r swap stack@ r> MOVSS/D ;
GENERIC: push-return-reg ( reg-class -- )
2008-10-05 22:30:29 -04:00
GENERIC: load-return-reg ( n reg-class -- )
GENERIC: store-return-reg ( n reg-class -- )
2007-09-20 18:09:08 -04:00
2008-04-19 05:52:34 -04:00
! Only used by inline allocation
2008-06-08 16:32:55 -04:00
HOOK: temp-reg-1 cpu ( -- reg )
HOOK: temp-reg-2 cpu ( -- reg )
2008-04-19 05:52:34 -04:00
2008-06-08 16:32:55 -04:00
HOOK: fixnum>slot@ cpu ( op -- )
HOOK: prepare-division cpu ( -- )
2007-09-20 18:09:08 -04:00
2008-10-07 17:42:11 -04:00
M: f load-literal
\ f tag-number MOV drop ;
M: fixnum load-literal
swap tag-fixnum MOV ;
2007-09-20 18:09:08 -04:00
2008-10-06 01:20:00 -04:00
: align-stack ( n -- n' )
2008-10-06 01:33:47 -04:00
os macosx? cpu x86.64? or [ 16 align ] when ;
2008-10-06 01:20:00 -04:00
M: x86 stack-frame-size ( n -- i )
3 cells + align-stack ;
2007-09-20 18:09:08 -04:00
2008-10-06 01:20:00 -04:00
: decr-stack-reg ( n -- )
dup 0 = [ drop ] [ stack-reg swap SUB ] if ;
M: x86 %prologue ( n -- )
2008-10-07 17:42:11 -04:00
temp-reg-1 0 MOV rc-absolute-cell rel-this
2008-10-08 04:51:44 -04:00
dup PUSH
2008-10-07 17:42:11 -04:00
temp-reg-1 PUSH
2008-10-08 04:51:44 -04:00
stack-reg swap 3 cells - SUB ;
2008-10-06 01:20:00 -04:00
: incr-stack-reg ( n -- )
2008-10-06 01:20:24 -04:00
dup 0 = [ drop ] [ stack-reg swap ADD ] if ;
2007-09-20 18:09:08 -04:00
2008-10-06 01:20:00 -04:00
M: x86 %epilogue ( n -- ) cell - incr-stack-reg ;
2007-09-20 18:09:08 -04:00
2008-05-09 00:21:46 -04:00
HOOK: %alien-global cpu ( symbol dll register -- )
2007-09-20 18:09:08 -04:00
M: x86 %prepare-alien-invoke
2007-09-20 18:09:08 -04:00
#! Save Factor stack pointers in case the C code calls a
#! callback which does a GC, which must reliably trace
#! all roots.
2008-10-07 17:42:11 -04:00
"stack_chain" f temp-reg-1 %alien-global
temp-reg-1 [] stack-reg MOV
temp-reg-1 [] cell SUB
temp-reg-1 2 cells [+] ds-reg MOV
temp-reg-1 3 cells [+] rs-reg MOV ;
2007-09-20 18:09:08 -04:00
M: x86 %call ( label -- ) CALL ;
2007-09-20 18:09:08 -04:00
M: x86 %jump-label ( label -- ) JMP ;
2007-09-20 18:09:08 -04:00
2008-10-07 21:00:38 -04:00
M: x86 %jump-f ( label reg -- )
2008-10-07 17:42:11 -04:00
\ f tag-number CMP JE ;
2007-09-20 18:09:08 -04:00
2008-10-07 21:00:38 -04:00
M: x86 %jump-t ( label reg -- )
2008-10-07 17:42:11 -04:00
\ f tag-number CMP JNE ;
2008-10-07 17:17:55 -04:00
2008-02-09 22:12:00 -05:00
: code-alignment ( -- n )
building get length dup cell align swap - ;
: align-code ( n -- )
0 <repetition> % ;
2008-10-07 21:00:38 -04:00
M:: x86 %dispatch ( src temp -- )
! Load jump table base. We use a temporary register
! since on AMD64 we have to load a 64-bit immediate. On
! x86, this is redundant.
! Untag and multiply to get a jump table offset
src fixnum>slot@
! Add jump table base
temp HEX: ffffffff MOV rc-absolute-cell rel-here
src temp ADD
src HEX: 7f [+] JMP
! Fix up the displacement above
code-alignment dup bootstrap-cell 8 = 15 9 ? +
building get dup pop* push
align-code ;
2007-09-20 18:09:08 -04:00
M: x86 %dispatch-label ( word -- )
0 cell, rc-absolute-cell rel-word ;
2007-09-20 18:09:08 -04:00
2008-10-07 17:42:11 -04:00
M: x86 %peek loc>operand MOV ;
2007-09-20 18:09:08 -04:00
2008-10-07 17:42:11 -04:00
M: x86 %replace loc>operand swap MOV ;
2008-10-07 17:17:55 -04:00
2008-06-08 16:32:55 -04:00
: (%inc) ( n reg -- ) swap cells dup 0 > [ ADD ] [ neg SUB ] if ;
2007-09-20 18:09:08 -04:00
M: x86 %inc-d ( n -- ) ds-reg (%inc) ;
2007-09-20 18:09:08 -04:00
M: x86 %inc-r ( n -- ) rs-reg (%inc) ;
2007-09-20 18:09:08 -04:00
2008-10-07 21:00:38 -04:00
M: x86 %copy ( dst src -- ) MOV ;
M: x86 fp-shadows-int? ( -- ? ) f ;
2007-09-20 18:09:08 -04:00
M: x86 value-structs? t ;
2007-09-20 18:09:08 -04:00
M: x86 small-enough? ( n -- ? )
2007-09-20 18:09:08 -04:00
HEX: -80000000 HEX: 7fffffff between? ;
: %untag ( reg -- ) tag-mask get bitnot AND ;
: %untag-fixnum ( reg -- ) tag-bits get SAR ;
: %tag-fixnum ( reg -- ) tag-bits get SHL ;
2008-10-13 00:32:14 -04:00
M: x86 %return ( -- ) 0 RET ;
2007-09-20 18:09:08 -04:00
! Alien intrinsics
M: x86 %unbox-byte-array ( dst src -- )
2008-10-07 17:42:11 -04:00
byte-array-offset [+] LEA ;
2007-09-20 18:09:08 -04:00
M: x86 %unbox-alien ( dst src -- )
2008-10-07 17:42:11 -04:00
alien-offset [+] MOV ;
2007-09-20 18:09:08 -04:00
M: x86 %unbox-f ( dst src -- )
2008-10-07 17:42:11 -04:00
drop 0 MOV ;
2007-09-20 18:09:08 -04:00
M: x86 %unbox-any-c-ptr ( dst src -- )
{ "is-byte-array" "end" "start" } [ define-label ] each
! Address is computed in ds-reg
ds-reg PUSH
ds-reg 0 MOV
! Object is stored in ds-reg
rs-reg PUSH
2008-10-07 17:42:11 -04:00
rs-reg swap MOV
! We come back here with displaced aliens
"start" resolve-label
! Is the object f?
2008-10-07 17:42:11 -04:00
rs-reg \ f tag-number CMP
"end" get JE
! Is the object an alien?
2008-01-02 19:36:36 -05:00
rs-reg header-offset [+] alien type-number tag-fixnum CMP
"is-byte-array" get JNE
! If so, load the offset and add it to the address
ds-reg rs-reg alien-offset [+] ADD
! Now recurse on the underlying alien
rs-reg rs-reg underlying-alien-offset [+] MOV
"start" get JMP
"is-byte-array" resolve-label
! Add byte array address to address being computed
ds-reg rs-reg ADD
! Add an offset to start of byte array's data
ds-reg byte-array-offset ADD
"end" resolve-label
! Done, store address in destination register
2008-10-07 17:42:11 -04:00
ds-reg MOV
! Restore rs-reg
rs-reg POP
! Restore ds-reg
ds-reg POP ;