2006-04-28 19:23:50 -04:00
|
|
|
! Copyright (C) 2005, 2006 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2006-04-03 02:18:56 -04:00
|
|
|
IN: compiler
|
|
|
|
USING: alien arrays assembler generic kernel kernel-internals
|
2006-04-28 19:23:50 -04:00
|
|
|
math sequences words ;
|
2005-09-04 19:24:24 -04:00
|
|
|
|
2005-09-05 17:14:15 -04:00
|
|
|
! x86 register assignments
|
2005-12-05 19:07:41 -05:00
|
|
|
! EAX, ECX, EDX vregs
|
2005-09-05 17:14:15 -04:00
|
|
|
! ESI datastack
|
|
|
|
! EBX callstack
|
|
|
|
|
2005-12-07 00:14:24 -05:00
|
|
|
: ds-reg ESI ; inline
|
|
|
|
: cs-reg EBX ; 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 ;
|
|
|
|
|
2005-12-07 00:14:24 -05:00
|
|
|
: remainder-reg EDX ; inline
|
|
|
|
|
2005-12-04 22:06:12 -05:00
|
|
|
: vregs { EAX ECX EDX } ; inline
|
2005-10-18 20:19:10 -04:00
|
|
|
|
2006-04-28 19:23:50 -04:00
|
|
|
: %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
|
|
|
|
2005-10-18 20:19:10 -04: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 { } ;
|
2005-12-24 16:08:15 -05:00
|
|
|
|
2006-01-24 20:20:20 -05:00
|
|
|
M: float-regs fastcall-regs drop { } ;
|
2005-10-18 20:19:10 -04:00
|
|
|
|
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
|
2005-12-20 03:22:01 -05:00
|
|
|
|
2006-04-28 19:23:50 -04:00
|
|
|
M: immediate load-literal ( dest literal -- )
|
|
|
|
address MOV ;
|
|
|
|
|
|
|
|
M: object load-literal ( dest literal -- )
|
|
|
|
add-literal [] MOV rel-absolute-cell rel-address ;
|
|
|
|
|
|
|
|
: (%call) ( label -- label )
|
|
|
|
dup postpone-word dup primitive? [ address-operand ] when ;
|
|
|
|
|
|
|
|
: %call ( label -- ) (%call) CALL ;
|
|
|
|
|
|
|
|
: %jump ( label -- ) %epilogue (%call) JMP ;
|
|
|
|
|
|
|
|
: %jump-label ( label -- ) JMP ;
|
|
|
|
|
|
|
|
: %jump-t ( label vreg -- )
|
|
|
|
v>operand f v>operand CMP JNE ;
|
|
|
|
|
|
|
|
: %dispatch ( vreg -- )
|
|
|
|
#! 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.
|
|
|
|
drop
|
|
|
|
<label> "end" set
|
|
|
|
! Untag and multiply to get a jump table offset
|
|
|
|
dup fixnum>slot@
|
|
|
|
! 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.
|
|
|
|
0 scratch HEX: ffffffff MOV "end" get absolute-cell
|
|
|
|
dup 0 scratch ADD
|
|
|
|
! Jump to jump table entry
|
|
|
|
dup [] JMP
|
|
|
|
! Align for better performance
|
|
|
|
compile-aligned
|
|
|
|
! Fix up jump table pointer
|
|
|
|
"end" get save-xt ;
|
|
|
|
|
|
|
|
: %return ( -- ) %epilogue RET ;
|
|
|
|
|
|
|
|
: %peek ( vreg loc -- ) [ v>operand ] 2apply MOV ;
|
|
|
|
|
|
|
|
: %replace ( vreg loc -- ) swap %peek ;
|
|
|
|
|
|
|
|
: (%inc) 0 input cells dup 0 > [ ADD ] [ neg SUB ] if ;
|
2005-12-20 03:22:01 -05:00
|
|
|
|
2006-04-28 19:23:50 -04:00
|
|
|
: %inc-d ( n -- ) ds-reg (%inc) ;
|
2005-12-23 01:41:33 -05:00
|
|
|
|
2006-04-28 19:23:50 -04:00
|
|
|
: %inc-r ( n -- ) cs-reg (%inc) ;
|