factor/library/compiler/x86/architecture.factor

127 lines
3.4 KiB
Factor
Raw Normal View History

2006-04-28 19:23:50 -04:00
! Copyright (C) 2005, 2006 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays assembler generic kernel kernel-internals
2006-04-29 17:28:51 -04:00
math memory namespaces sequences words ;
2006-04-29 18:33:05 -04:00
IN: compiler
2005-09-05 17:14:15 -04:00
! x86 register assignments
2006-05-04 18:08:52 -04:00
! EAX, ECX, EDX integer vregs
! XMM0 - XMM7 float vregs
2005-09-05 17:14:15 -04:00
! ESI datastack
! EBX callstack
2006-05-04 18:08:52 -04:00
! AMD64 redefines a lot of words in this file
2005-12-07 00:14:24 -05:00
: ds-reg ESI ; inline
: cs-reg EBX ; inline
2006-04-29 17:28:51 -04:00
: remainder-reg EDX ; inline
2006-04-28 19:23:50 -04:00
: reg-stack ( n reg -- op ) swap cells neg [+] ;
M: ds-loc v>operand ds-loc-n ds-reg reg-stack ;
M: cs-loc v>operand cs-loc-n cs-reg reg-stack ;
: %alien-invoke ( symbol dll -- )
2005-12-11 15:14:41 -05:00
2dup dlsym CALL rel-relative rel-dlsym ;
2005-12-10 01:02:13 -05:00
: compile-c-call* ( symbol dll args -- operands )
2005-12-10 03:03:45 -05:00
reverse-slice
2006-04-28 19:23:50 -04:00
[ [ PUSH ] each %alien-invoke ] keep
2005-12-11 18:48:42 -05:00
[ drop EDX POP ] each ;
2005-12-10 01:02:13 -05:00
! On x86, parameters are never passed in registers.
2005-12-24 16:08:15 -05:00
M: int-regs return-reg drop EAX ;
2006-01-24 20:20:20 -05:00
M: int-regs fastcall-regs drop { } ;
2006-05-04 18:08:52 -04:00
M: int-regs vregs drop { EAX ECX EDX } ;
2005-12-24 16:08:15 -05:00
2006-01-24 20:20:20 -05:00
M: float-regs fastcall-regs drop { } ;
2006-05-04 18:08:52 -04:00
M: float-regs vregs drop { XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 } ;
2005-12-04 22:55:02 -05:00
: address-operand ( address -- operand )
#! On x86, we can always use an address as an operand
#! directly.
; inline
: fixnum>slot@ 1 SHR ; inline
2005-12-07 03:37:05 -05:00
: prepare-division CDQ ; inline
2006-05-05 20:06:57 -04:00
: fp-scratch ( -- vreg )
"fp-scratch" get [
T{ int-regs } alloc-reg dup "fp-scratch" set
] unless* ;
: unboxify-float ( obj vreg quot -- | quot: obj int-vreg )
2006-05-05 02:08:37 -04:00
#! The SSE2 code here will never be generated unless SSE2
#! intrinsics are loaded.
over [ float-regs? ] is? [
2006-05-05 20:06:57 -04:00
swap >r fp-scratch [ swap call ] keep
r> swap [ v>operand ] 2apply float-offset [+] MOVSD
] [
call
] if ; inline
2006-05-05 20:06:57 -04:00
: literal-template
#! All literals go into integer registers unless SSE2
#! intrinsics are loaded.
length f <array> ;
2006-04-29 18:33:05 -04:00
M: immediate load-literal ( literal vreg -- )
v>operand swap v>operand MOV ;
: load-indirect ( literal vreg -- )
v>operand swap add-literal [] MOV
rel-absolute-cell rel-address ;
2006-04-28 19:23:50 -04:00
2006-04-29 18:33:05 -04:00
M: object load-literal ( literal vreg -- )
[ load-indirect ] unboxify-float ;
2006-04-28 19:23:50 -04:00
: (%call) ( label -- label )
dup postpone-word dup primitive? [ address-operand ] when ;
: %call ( label -- ) (%call) CALL ;
: %jump ( label -- ) %epilogue (%call) JMP ;
: %jump-label ( label -- ) JMP ;
2006-04-29 17:28:51 -04:00
: %jump-t ( label -- ) "flag" operand f v>operand CMP JNE ;
2006-04-28 19:23:50 -04:00
: %dispatch ( -- )
2006-04-28 19:23:50 -04:00
#! Compile a piece of code that jumps to an offset in a
#! jump table indexed by the fixnum at the top of the stack.
#! The jump table must immediately follow this macro.
<label> "end" set
! Untag and multiply to get a jump table offset
"n" operand fixnum>slot@
2006-04-28 19:23:50 -04:00
! Add to jump table base. We use a temporary register since
! on AMD4 we have to load a 64-bit immediate. On x86, this
! is redundant.
2006-04-29 18:33:05 -04:00
"scratch" operand HEX: ffffffff MOV "end" get absolute-cell
"n" operand "scratch" operand ADD
2006-04-28 19:23:50 -04:00
! Jump to jump table entry
"n" operand [] JMP
2006-04-28 19:23:50 -04:00
! Align for better performance
compile-aligned
! Fix up jump table pointer
"end" get save-xt ;
: %return ( -- ) %epilogue RET ;
2006-05-05 20:06:57 -04:00
: vreg-mov swap [ v>operand ] 2apply MOV ;
: %peek ( vreg loc -- )
2006-05-05 20:06:57 -04:00
swap [ vreg-mov ] unboxify-float ;
2006-05-05 20:06:57 -04:00
GENERIC: (%replace) ( vreg loc reg-class -- )
M: int-regs (%replace) drop vreg-mov ;
: %replace ( vreg loc -- ) over (%replace) ;
2006-04-28 19:23:50 -04:00
2006-04-29 18:33:05 -04:00
: (%inc) swap cells dup 0 > [ ADD ] [ neg SUB ] if ;
2006-04-28 19:23:50 -04:00
: %inc-d ( n -- ) ds-reg (%inc) ;
2006-04-28 19:23:50 -04:00
: %inc-r ( n -- ) cs-reg (%inc) ;