1 ! Copyright (C) 2011 Erik Charlebois
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs sequences kernel combinators
4 classes.algebra byte-arrays make math math.order math.ranges
5 system namespaces locals layouts words alien alien.accessors
6 alien.c-types alien.complex alien.data alien.libraries
7 literals cpu.architecture cpu.ppc.assembler
8 compiler.cfg.registers compiler.cfg.instructions
9 compiler.cfg.comparisons compiler.codegen.fixup
10 compiler.cfg.intrinsics compiler.cfg.stack-frame
11 compiler.cfg.build-stack-frame compiler.units compiler.constants
12 compiler.codegen vm memory fry io prettyprint ;
13 QUALIFIED-WITH: alien.c-types c
14 FROM: cpu.ppc.assembler => B ;
15 FROM: layouts => cell ;
19 ! PowerPC register assignments:
20 ! r0: reserved for function prolog/epilogues
21 ! r1: call stack register
22 ! r2: toc register / system reserved
23 ! r3-r12: integer vregs
28 ! r17-r29: integer vregs
29 ! r30: integer scratch
35 HOOK: lr-save os ( -- n )
36 HOOK: has-toc os ( -- ? )
37 HOOK: reserved-area-size os ( -- n )
38 HOOK: allows-null-dereference os ( -- ? )
40 M: label B ( label -- ) [ 0 B ] dip rc-relative-ppc-3-pc label-fixup ;
41 M: label BL ( label -- ) [ 0 BL ] dip rc-relative-ppc-3-pc label-fixup ;
42 M: label BC ( bo bi label -- ) [ 0 BC ] dip rc-relative-ppc-2-pc label-fixup ;
44 CONSTANT: scratch-reg 30
45 CONSTANT: fp-scratch-reg 30
50 enable-float-intrinsics
52 M: ppc vector-regs ( -- reg-class )
55 M: ppc machine-registers ( -- assoc )
57 { int-regs $[ 3 12 [a,b] 17 29 [a,b] append ] }
58 { float-regs $[ 0 29 [a,b] ] }
61 M: ppc frame-reg ( -- reg ) 31 ;
62 M: ppc.32 vm-stack-space ( -- n ) 16 ;
63 M: ppc.64 vm-stack-space ( -- n ) 32 ;
64 M: ppc complex-addressing? ( -- ? ) f ;
66 ! PW1-PW8 parameter save slots
67 : param-save-size ( -- n ) 8 cells ; foldable
70 : factor-area-size ( -- n ) 2 cells ; foldable
72 : spill@ ( n -- offset )
73 spill-offset reserved-area-size + param-save-size + ;
75 : param@ ( n -- offset )
76 reserved-area-size + ;
78 M: ppc gc-root-offset ( spill-slot -- n )
82 [ -16 shift 0xffff bitand LIS ]
83 [ [ dup ] dip 0xffff bitand ORI ] 2bi ;
87 [ nip -48 shift 0xffff bitand LIS ]
88 [ -32 shift 0xffff bitand ORI ]
90 [ -16 shift 0xffff bitand ORIS ]
94 HOOK: %clear-tag-bits cpu ( dst src -- )
95 M: ppc.32 %clear-tag-bits tag-bits get CLRRWI ;
96 M: ppc.64 %clear-tag-bits tag-bits get CLRRDI ;
98 HOOK: %store-cell cpu ( dst src offset -- )
99 M: ppc.32 %store-cell STW ;
100 M: ppc.64 %store-cell STD ;
102 HOOK: %store-cell-x cpu ( dst src offset -- )
103 M: ppc.32 %store-cell-x STWX ;
104 M: ppc.64 %store-cell-x STDX ;
106 HOOK: %store-cell-update cpu ( dst src offset -- )
107 M: ppc.32 %store-cell-update STWU ;
108 M: ppc.64 %store-cell-update STDU ;
110 HOOK: %load-cell cpu ( dst src offset -- )
111 M: ppc.32 %load-cell LWZ ;
112 M: ppc.64 %load-cell LD ;
114 HOOK: %trap-null cpu ( src -- )
116 allows-null-dereference [ 0 TWEQI ] [ drop ] if ;
118 allows-null-dereference [ 0 TDEQI ] [ drop ] if ;
120 HOOK: %load-cell-x cpu ( dst src offset -- )
121 M: ppc.32 %load-cell-x LWZX ;
122 M: ppc.64 %load-cell-x LDX ;
124 HOOK: %load-cell-imm cpu ( dst imm -- )
125 M: ppc.32 %load-cell-imm LOAD32 ;
126 M: ppc.64 %load-cell-imm LOAD64 ;
128 HOOK: %compare-cell cpu ( cr lhs rhs -- )
129 M: ppc.32 %compare-cell CMPW ;
130 M: ppc.64 %compare-cell CMPD ;
132 HOOK: %compare-cell-imm cpu ( cr lhs imm -- )
133 M: ppc.32 %compare-cell-imm CMPWI ;
134 M: ppc.64 %compare-cell-imm CMPDI ;
136 HOOK: %load-cell-imm-rc cpu ( -- rel-class )
137 M: ppc.32 %load-cell-imm-rc rc-absolute-ppc-2/2 ;
138 M: ppc.64 %load-cell-imm-rc rc-absolute-ppc-2/2/2/2 ;
140 M: ppc.32 %load-immediate ( reg val -- )
141 dup -0x8000 0x7fff between? [ LI ] [ LOAD32 ] if ;
142 M: ppc.64 %load-immediate ( reg val -- )
143 dup -0x8000 0x7fff between? [ LI ] [ LOAD64 ] if ;
145 M: ppc %load-reference ( reg obj -- )
146 [ [ 0 %load-cell-imm ] [ %load-cell-imm-rc rel-literal ] bi* ]
147 [ \ f type-number LI ]
150 M:: ppc %load-float ( dst val -- )
151 scratch-reg 0 %load-cell-imm val %load-cell-imm-rc rel-binary-literal
152 dst scratch-reg 0 LFS ;
154 M:: ppc %load-double ( dst val -- )
155 scratch-reg 0 %load-cell-imm val %load-cell-imm-rc rel-binary-literal
156 dst scratch-reg 0 LFD ;
158 M:: ppc %load-vector ( dst val rep -- )
159 scratch-reg 0 %load-cell-imm val %load-cell-imm-rc rel-binary-literal
160 dst 0 scratch-reg LVX ;
162 GENERIC: loc-reg ( loc -- reg )
163 M: ds-loc loc-reg drop ds-reg ;
164 M: rs-loc loc-reg drop rs-reg ;
166 ! Load value at stack location loc into vreg.
167 M: ppc %peek ( vreg loc -- )
168 [ loc-reg ] [ n>> cells neg ] bi %load-cell ;
170 ! Replace value at stack location loc with value in vreg.
171 M: ppc %replace ( vreg loc -- )
172 [ loc-reg ] [ n>> cells neg ] bi %store-cell ;
174 ! Replace value at stack location with an immediate value.
175 M:: ppc %replace-imm ( src loc -- )
177 loc n>> cells neg :> offset
180 drop scratch-reg \ f type-number LI ] }
182 [ scratch-reg ] dip tag-fixnum LI ] }
183 [ scratch-reg 0 LI rc-absolute rel-literal ]
185 scratch-reg reg offset %store-cell ;
187 ! Increment data stack pointer by n cells.
188 M: ppc %inc-d ( n -- )
189 [ ds-reg ds-reg ] dip cells ADDI ;
191 ! Increment retain stack pointer by n cells.
192 M: ppc %inc-r ( n -- )
193 [ rs-reg rs-reg ] dip cells ADDI ;
195 M: ppc stack-frame-size ( stack-frame -- i )
202 M: ppc %call ( word -- )
203 0 BL rc-relative-ppc-3-pc rel-word-pic ;
205 : instrs ( n -- b ) 4 * ; inline
207 M: ppc %jump ( word -- )
208 6 0 %load-cell-imm 1 instrs %load-cell-imm-rc rel-here
209 0 B rc-relative-ppc-3-pc rel-word-pic-tail ;
211 M: ppc %dispatch ( src temp -- )
212 [ nip 0 %load-cell-imm 3 instrs %load-cell-imm-rc rel-here ]
213 [ swap dupd %load-cell-x ]
214 [ nip MTCTR ] 2tri BCTR ;
216 M: ppc %slot ( dst obj slot scale tag -- )
217 [ 0 assert= ] bi@ %load-cell-x ;
219 M: ppc %slot-imm ( dst obj slot tag -- )
220 slot-offset scratch-reg swap LI
221 scratch-reg %load-cell-x ;
223 M: ppc %set-slot ( src obj slot scale tag -- )
224 [ 0 assert= ] bi@ %store-cell-x ;
226 M: ppc %set-slot-imm ( src obj slot tag -- )
227 slot-offset [ scratch-reg ] dip LI scratch-reg %store-cell-x ;
229 M: ppc %jump-label B ;
232 M: ppc %add-imm ADDI ;
234 M: ppc %sub-imm SUBI ;
235 M: ppc.32 %mul MULLW ;
236 M: ppc.64 %mul MULLD ;
237 M: ppc %mul-imm MULLI ;
239 M: ppc %and-imm ANDI. ;
243 M: ppc %xor-imm XORI ;
246 M: ppc.32 %shl-imm SLWI ;
247 M: ppc.64 %shl-imm SLDI ;
250 M: ppc.32 %shr-imm SRWI ;
251 M: ppc.64 %shr-imm SRDI ;
252 M: ppc.32 %sar SRAW ;
253 M: ppc.64 %sar SRAD ;
254 M: ppc.32 %sar-imm SRAWI ;
255 M: ppc.64 %sar-imm SRADI ;
256 M: ppc.32 %min [ 0 CMPW ] [ 0 ISEL ] 2bi ;
257 M: ppc.64 %min [ 0 CMPD ] [ 0 ISEL ] 2bi ;
258 M: ppc.32 %max [ 0 CMPW ] [ swap 0 ISEL ] 2bi ;
259 M: ppc.64 %max [ 0 CMPD ] [ swap 0 ISEL ] 2bi ;
262 M: ppc.32 %log2 [ CNTLZW ] [ drop dup NEG ] [ drop dup 31 ADDI ] 2tri ;
263 M: ppc.64 %log2 [ CNTLZD ] [ drop dup NEG ] [ drop dup 63 ADDI ] 2tri ;
264 M: ppc.32 %bit-count POPCNTW ;
265 M: ppc.64 %bit-count POPCNTD ;
267 M: ppc %copy ( dst src rep -- )
268 2over eq? [ 3drop ] [
270 { tagged-rep [ MR ] }
272 { float-rep [ FMR ] }
273 { double-rep [ FMR ] }
274 { vector-rep [ dup VOR ] }
275 { scalar-rep [ dup VOR ] }
279 :: overflow-template ( label dst src1 src2 cc insn -- )
282 dst src2 src1 insn call
284 { cc-o [ 0 label BSO ] }
285 { cc/o [ 0 label BNS ] }
288 M: ppc %fixnum-add ( label dst src1 src2 cc -- )
289 [ ADDO. ] overflow-template ;
291 M: ppc %fixnum-sub ( label dst src1 src2 cc -- )
292 [ SUBFO. ] overflow-template ;
294 M: ppc.32 %fixnum-mul ( label dst src1 src2 cc -- )
295 [ MULLWO. ] overflow-template ;
296 M: ppc.64 %fixnum-mul ( label dst src1 src2 cc -- )
297 [ MULLDO. ] overflow-template ;
299 M: ppc %add-float FADD ;
300 M: ppc %sub-float FSUB ;
301 M: ppc %mul-float FMUL ;
302 M: ppc %div-float FDIV ;
304 M: ppc %min-float ( dst src1 src2 -- )
305 2dup [ scratch-reg ] 2dip FSUB
306 [ scratch-reg ] 2dip FSEL ;
308 M: ppc %max-float ( dst src1 src2 -- )
309 2dup [ scratch-reg ] 2dip FSUB
310 [ scratch-reg ] 2dip FSEL ;
313 M: ppc %single>double-float FMR ;
314 M: ppc %double>single-float FRSP ;
316 M: ppc integer-float-needs-stack-frame? t ;
318 : scratch@ ( n -- offset )
319 reserved-area-size + ;
321 M:: ppc.32 %integer>float ( dst src -- )
322 ! Sign extend to a doubleword and store.
323 scratch-reg src 31 %sar-imm
324 scratch-reg 1 0 scratch@ STW
326 ! Load back doubleword into FPR and convert from integer.
330 M:: ppc.64 %integer>float ( dst src -- )
335 M:: ppc.32 %float>integer ( dst src -- )
336 fp-scratch-reg src FRIZ
337 fp-scratch-reg fp-scratch-reg FCTIWZ
338 fp-scratch-reg 1 0 scratch@ STFD
339 dst 1 4 scratch@ LWZ ;
341 M:: ppc.64 %float>integer ( dst src -- )
342 fp-scratch-reg src FRIZ
343 fp-scratch-reg fp-scratch-reg FCTID
344 fp-scratch-reg 1 0 scratch@ STFD
345 dst 1 0 scratch@ LD ;
347 ! Scratch registers by register class.
348 : scratch-regs ( -- regs )
351 { float-regs { 30 } }
354 ! Return values of this class go here
355 M: ppc return-regs ( -- regs )
357 { int-regs { 3 4 5 6 } }
358 { float-regs { 1 2 3 4 } }
361 ! Is this structure small enough to be returned in registers?
362 M: ppc return-struct-in-registers? ( c-type -- ? )
363 lookup-c-type return-in-registers?>> ;
365 ! If t, floats are never passed in param regs
366 M: ppc float-on-stack? ( -- ? ) f ;
368 ! If t, the struct return pointer is never passed in a param reg
369 M: ppc struct-return-on-stack? ( -- ? ) f ;
371 GENERIC: load-param ( reg src -- )
372 M: integer load-param ( reg src -- ) int-rep %copy ;
373 M: spill-slot load-param ( reg src -- ) [ 1 ] dip n>> spill@ %load-cell ;
375 GENERIC: store-param ( reg dst -- )
376 M: integer store-param ( reg dst -- ) swap int-rep %copy ;
377 M: spill-slot store-param ( reg dst -- ) [ 1 ] dip n>> spill@ %store-cell ;
379 M:: ppc %unbox ( dst src func rep -- )
385 M:: ppc %unbox-long-long ( dst1 dst2 src func -- )
392 M:: ppc %local-allot ( dst size align offset -- )
393 dst 1 offset local-allot-offset reserved-area-size + ADDI ;
395 : param-reg ( n rep -- reg )
396 reg-class-of cdecl param-regs at nth ;
398 M:: ppc %box ( dst src func rep gc-map -- )
401 func f gc-map %c-invoke
404 M:: ppc %box-long-long ( dst src1 src2 func gc-map -- )
408 func f gc-map %c-invoke
411 M:: ppc %save-context ( temp1 temp2 -- )
413 1 temp1 "callstack-top" context-field-offset %store-cell
414 ds-reg temp1 "datastack" context-field-offset %store-cell
415 rs-reg temp1 "retainstack" context-field-offset %store-cell ;
417 M:: ppc %c-invoke ( name dll gc-map -- )
418 11 0 %load-cell-imm name dll %load-cell-imm-rc rel-dlsym
420 2 0 %load-cell-imm name dll %load-cell-imm-rc rel-dlsym-toc
426 : return-reg ( rep -- reg )
427 reg-class-of return-regs at first ;
429 : scratch-reg-class ( rep -- reg )
430 reg-class-of scratch-regs at first ;
432 :: store-stack-param ( vreg rep n -- )
433 rep scratch-reg-class rep vreg %reload
434 rep scratch-reg-class n param@ rep {
435 { int-rep [ [ 1 ] dip %store-cell ] }
436 { tagged-rep [ [ 1 ] dip %store-cell ] }
437 { float-rep [ [ 1 ] dip STFS ] }
438 { double-rep [ [ 1 ] dip STFD ] }
439 { vector-rep [ scratch-reg swap LI 1 scratch-reg STVX ] }
440 { scalar-rep [ scratch-reg swap LI 1 scratch-reg STVX ] }
443 :: store-reg-param ( vreg rep reg -- )
444 reg rep vreg %reload ;
446 : discard-reg-param ( rep reg -- )
449 :: load-reg-param ( vreg rep reg -- )
450 reg rep vreg %spill ;
452 :: load-stack-param ( vreg rep n -- )
453 rep scratch-reg-class n param@ rep {
454 { int-rep [ [ frame-reg ] dip %load-cell ] }
455 { tagged-rep [ [ frame-reg ] dip %load-cell ] }
456 { float-rep [ [ frame-reg ] dip LFS ] }
457 { double-rep [ [ frame-reg ] dip LFD ] }
458 { vector-rep [ scratch-reg swap LI frame-reg scratch-reg LVX ] }
459 { scalar-rep [ scratch-reg swap LI frame-reg scratch-reg LVX ] }
461 rep scratch-reg-class rep vreg %spill ;
463 :: emit-alien-insn ( reg-inputs stack-inputs reg-outputs dead-outputs cleanup stack-size quot -- )
464 stack-inputs [ first3 store-stack-param ] each
465 reg-inputs [ first3 store-reg-param ] each
467 reg-outputs [ first3 load-reg-param ] each
468 dead-outputs [ first2 discard-reg-param ] each
471 M: ppc %alien-invoke ( reg-inputs stack-inputs reg-outputs
472 dead-outputs cleanup stack-size
473 symbols dll gc-map -- )
474 '[ _ _ _ %c-invoke ] emit-alien-insn ;
476 M:: ppc %alien-indirect ( src reg-inputs stack-inputs
477 reg-outputs dead-outputs cleanup
478 stack-size gc-map -- )
479 reg-inputs stack-inputs reg-outputs dead-outputs cleanup stack-size [
482 2 11 1 cells %load-cell
483 11 11 0 cells %load-cell
492 M: ppc %alien-assembly ( reg-inputs stack-inputs reg-outputs
493 dead-outputs cleanup stack-size quot
495 '[ _ _ gc-map set call( -- ) ] emit-alien-insn ;
497 M: ppc %callback-inputs ( reg-outputs stack-outputs -- )
498 [ [ first3 load-reg-param ] each ]
499 [ [ first3 load-stack-param ] each ] bi*
502 "begin_callback" f f %c-invoke ;
504 M: ppc %callback-outputs ( reg-inputs -- )
506 "end_callback" f f %c-invoke
507 [ first3 store-reg-param ] each ;
509 M: ppc stack-cleanup ( stack-size return abi -- n )
512 M: ppc fused-unboxing? f ;
514 M: ppc %alien-global ( register symbol dll -- )
515 [ 0 %load-cell-imm ] 2dip %load-cell-imm-rc rel-dlsym ;
517 M: ppc %vm-field ( dst field -- ) [ vm-reg ] dip %load-cell ;
518 M: ppc %set-vm-field ( src field -- ) [ vm-reg ] dip %store-cell ;
520 M: ppc %unbox-alien ( dst src -- )
521 scratch-reg alien-offset LI scratch-reg %load-cell-x ;
523 ! Convert a c-ptr object to a raw C pointer.
526 ! else if ((src & tag_mask) == ALIEN_TYPE)
527 ! dst = ((alien*)src)->address;
528 ! else // Assume (src & tag_mask) == BYTE_ARRAY_TYPE
529 ! dst = ((byte_array*)src) + 1;
530 M:: ppc %unbox-any-c-ptr ( dst src -- )
535 0 src \ f type-number %compare-cell-imm
538 ! Is the object an alien?
539 dst src tag-mask get ANDI.
540 ! Assume unboxing a byte-array.
541 0 dst alien type-number %compare-cell-imm
542 dst src byte-array-offset ADDI
546 scratch-reg alien-offset LI
547 dst src scratch-reg %load-cell-x
551 ! Be very careful with this. It cannot be used as an immediate
552 ! offset to a load or store.
553 : alien@ ( n -- n' ) cells alien type-number - ;
555 ! Convert a raw C pointer to a c-ptr object.
559 ! dst = allot_alien(NULL);
560 ! dst->base = F_TYPE;
561 ! dst->expired = F_TYPE;
562 ! dst->displacement = src;
563 ! dst->address = src;
565 M:: ppc %box-alien ( dst src temp -- )
570 dst \ f type-number LI
571 0 src 0 %compare-cell-imm
574 ! Allocate and initialize an alien object.
575 dst 5 cells alien temp %allot
576 temp \ f type-number LI
577 scratch-reg dst %clear-tag-bits
578 temp scratch-reg 1 cells %store-cell
579 temp scratch-reg 2 cells %store-cell
580 src scratch-reg 3 cells %store-cell
581 src scratch-reg 4 cells %store-cell
587 ! dst->displacement = displacement;
588 ! dst->displacement = displacement;
589 :: box-displaced-alien/f ( dst displacement base -- )
590 scratch-reg dst %clear-tag-bits
591 base scratch-reg 1 cells %store-cell
592 displacement scratch-reg 3 cells %store-cell
593 displacement scratch-reg 4 cells %store-cell ;
595 ! dst->base = base->base;
596 ! dst->displacement = base->displacement + displacement;
597 ! dst->address = base->address + displacement;
598 :: box-displaced-alien/alien ( dst displacement base temp -- )
599 ! Set new alien's base to base.base
600 scratch-reg 1 alien@ LI
601 temp base scratch-reg %load-cell-x
602 temp dst scratch-reg %store-cell-x
604 ! Compute displacement
605 scratch-reg 3 alien@ LI
606 temp base scratch-reg %load-cell-x
607 temp temp displacement ADD
608 temp dst scratch-reg %store-cell-x
611 scratch-reg 4 alien@ LI
612 temp base scratch-reg %load-cell-x
613 temp temp displacement ADD
614 temp dst scratch-reg %store-cell-x ;
617 ! dst->displacement = displacement
618 ! dst->address = base + sizeof(byte_array) + displacement
619 :: box-displaced-alien/byte-array ( dst displacement base temp -- )
620 scratch-reg dst %clear-tag-bits
621 base scratch-reg 1 cells %store-cell
622 displacement scratch-reg 3 cells %store-cell
623 temp base byte-array-offset ADDI
624 temp temp displacement ADD
625 temp scratch-reg 4 cells %store-cell ;
627 ! if (base == F_TYPE)
628 ! box_displaced_alien_f(dst, displacement, base);
629 ! else if ((base & tag_mask) == ALIEN_TYPE)
630 ! box_displaced_alien_alien(dst, displacement, base, temp);
632 ! box_displaced_alien_byte_array(dst, displacement, base, temp);
633 :: box-displaced-alien/dynamic ( dst displacement base temp -- )
635 "not-alien" define-label
638 0 base \ f type-number %compare-cell-imm
640 dst displacement base box-displaced-alien/f
644 "not-f" resolve-label
645 temp base tag-mask get ANDI.
646 0 temp alien type-number %compare-cell-imm
647 0 "not-alien" get BNE
648 dst displacement base temp box-displaced-alien/alien
651 ! Assume base is a byte array.
652 "not-alien" resolve-label
653 dst displacement base temp box-displaced-alien/byte-array ;
655 ! if (displacement == 0)
658 ! dst = allot_alien(NULL);
659 ! dst->expired = F_TYPE;
660 ! if (is_subclass(base_class, F_TYPE))
661 ! box_displaced_alien_f(dst, displacement, base);
662 ! else if (is_subclass(base_class, ALIEN_TYPE))
663 ! box_displaced_alien_alien(dst, displacement, base, temp);
664 ! else if (is_subclass(base_class, BYTE_ARRAY_TYPE))
665 ! box_displaced_alien_byte_array(dst, displacement, base, temp);
667 ! box_displaced_alien_dynamic(dst, displacement, base, temp);
669 M:: ppc %box-displaced-alien ( dst displacement base temp base-class -- )
673 ! If displacement is zero, return the base.
675 0 displacement 0 %compare-cell-imm
678 ! Displacement is non-zero, we're going to be allocating a new
680 dst 5 cells alien temp %allot
683 temp \ f type-number %load-immediate
684 scratch-reg 2 alien@ LI
685 temp dst scratch-reg %store-cell-x
687 dst displacement base temp
689 { [ base-class \ f class<= ] [ drop box-displaced-alien/f ] }
690 { [ base-class \ alien class<= ] [ box-displaced-alien/alien ] }
691 { [ base-class \ byte-array class<= ] [ box-displaced-alien/byte-array ] }
692 [ box-displaced-alien/dynamic ]
698 M:: ppc.32 %convert-integer ( dst src c-type -- )
700 { c:char [ dst src 24 CLRLWI dst dst EXTSB ] }
701 { c:uchar [ dst src 24 CLRLWI ] }
702 { c:short [ dst src 16 CLRLWI dst dst EXTSH ] }
703 { c:ushort [ dst src 16 CLRLWI ] }
708 M:: ppc.64 %convert-integer ( dst src c-type -- )
710 { c:char [ dst src 56 CLRLDI dst dst EXTSB ] }
711 { c:uchar [ dst src 56 CLRLDI ] }
712 { c:short [ dst src 48 CLRLDI dst dst EXTSH ] }
713 { c:ushort [ dst src 48 CLRLDI ] }
714 { c:int [ dst src 32 CLRLDI dst dst EXTSW ] }
715 { c:uint [ dst src 32 CLRLDI ] }
720 M: ppc.32 %load-memory-imm ( dst base offset rep c-type -- )
724 { c:char [ [ dup ] 2dip LBZ dup EXTSB ] }
734 { float-rep [ LFS ] }
735 { double-rep [ LFD ] }
739 M: ppc.64 %load-memory-imm ( dst base offset rep c-type -- )
743 { c:char [ [ dup ] 2dip LBZ dup EXTSB ] }
749 { c:longlong [ [ scratch-reg ] dip LI scratch-reg LDX ] }
750 { c:ulonglong [ [ scratch-reg ] dip LI scratch-reg LDX ] }
754 { int-rep [ [ scratch-reg ] dip LI scratch-reg LDX ] }
755 { float-rep [ [ scratch-reg ] dip LI scratch-reg LFSX ] }
756 { double-rep [ [ scratch-reg ] dip LI scratch-reg LFDX ] }
761 M: ppc.32 %load-memory ( dst base displacement scale offset rep c-type -- )
762 [ [ 0 assert= ] bi@ ] 2dip
766 { c:char [ [ LBZX ] [ drop dup EXTSB ] 2bi ] }
769 { c:ushort [ LHZX ] }
776 { float-rep [ LFSX ] }
777 { double-rep [ LFDX ] }
781 M: ppc.64 %load-memory ( dst base displacement scale offset rep c-type -- )
782 [ [ 0 assert= ] bi@ ] 2dip
786 { c:char [ [ LBZX ] [ drop dup EXTSB ] 2bi ] }
789 { c:ushort [ LHZX ] }
792 { c:longlong [ LDX ] }
793 { c:ulonglong [ LDX ] }
798 { float-rep [ LFSX ] }
799 { double-rep [ LFDX ] }
804 M: ppc.32 %store-memory-imm ( src base offset rep c-type -- )
817 { float-rep [ STFS ] }
818 { double-rep [ STFD ] }
822 M: ppc.64 %store-memory-imm ( src base offset rep c-type -- )
831 { c:longlong [ [ scratch-reg ] dip LI scratch-reg STDX ] }
832 { c:ulonglong [ [ scratch-reg ] dip LI scratch-reg STDX ] }
836 { int-rep [ [ scratch-reg ] dip LI scratch-reg STDX ] }
837 { float-rep [ [ scratch-reg ] dip LI scratch-reg STFSX ] }
838 { double-rep [ [ scratch-reg ] dip LI scratch-reg STFDX ] }
842 M: ppc.32 %store-memory ( src base displacement scale offset rep c-type -- )
843 [ [ 0 assert= ] bi@ ] 2dip
849 { c:ushort [ STHX ] }
856 { float-rep [ STFSX ] }
857 { double-rep [ STFDX ] }
861 M: ppc.64 %store-memory ( src base displacement scale offset rep c-type -- )
862 [ [ 0 assert= ] bi@ ] 2dip
868 { c:ushort [ STHX ] }
871 { c:longlong [ STDX ] }
872 { c:ulonglong [ STDX ] }
877 { float-rep [ STFSX ] }
878 { double-rep [ STFDX ] }
882 M:: ppc %allot ( dst size class nursery-ptr -- )
883 ! dst = vm->nursery.here;
884 nursery-ptr vm-reg "nursery" vm-field-offset ADDI
885 dst nursery-ptr 0 %load-cell
886 ! vm->nursery.here += align(size, data_alignment);
887 scratch-reg dst size data-alignment get align ADDI
888 scratch-reg nursery-ptr 0 %store-cell
889 ! ((object*) dst)->header = type_number << 2;
890 scratch-reg class type-number tag-header LI
891 scratch-reg dst 0 %store-cell
893 dst dst class type-number ORI ;
895 :: (%write-barrier) ( temp1 temp2 -- )
896 scratch-reg card-mark LI
897 ! *(char *)(cards_offset + ((cell)slot_ptr >> card_bits))
899 temp1 temp1 card-bits %shr-imm
900 temp2 0 %load-cell-imm %load-cell-imm-rc rel-cards-offset
901 scratch-reg temp1 temp2 STBX
902 ! *(char *)(decks_offset + ((cell)slot_ptr >> deck_bits))
904 temp1 temp1 deck-bits card-bits - %shr-imm
905 temp2 0 %load-cell-imm %load-cell-imm-rc rel-decks-offset
906 scratch-reg temp1 temp2 STBX ;
908 M:: ppc %write-barrier ( src slot scale tag temp1 temp2 -- )
909 scale 0 assert= tag 0 assert=
911 temp1 temp2 (%write-barrier) ;
913 M:: ppc %write-barrier-imm ( src slot tag temp1 temp2 -- )
914 temp1 src slot tag slot-offset ADDI
915 temp1 temp2 (%write-barrier) ;
917 M:: ppc %check-nursery-branch ( label size cc temp1 temp2 -- )
918 ! if (vm->nursery.here + size >= vm->nursery.end) ...
919 temp1 vm-reg "nursery" vm-field-offset %load-cell
920 temp2 vm-reg "nursery" vm-field-offset 2 cells + %load-cell
921 temp1 temp1 size ADDI
922 0 temp1 temp2 %compare-cell
924 { cc<= [ 0 label BLE ] }
925 { cc/<= [ 0 label BGT ] }
928 M: ppc %call-gc ( gc-map -- )
929 \ minor-gc %call gc-map-here ;
931 M:: ppc %prologue ( stack-size -- )
933 0 1 lr-save %store-cell
934 11 0 %load-cell-imm %load-cell-imm-rc rel-this
935 11 1 2 cells neg %store-cell
937 11 1 1 cells neg %store-cell
938 1 1 stack-size neg %store-cell-update ;
940 ! At the end of each word that calls a subroutine, we store
941 ! the previous link register value in r0 by popping it off
942 ! the stack, set the link register to the contents of r0,
943 ! and jump to the link register.
944 M:: ppc %epilogue ( stack-size -- )
946 0 1 lr-save %load-cell
949 :: (%boolean) ( dst temp branch1 branch2 -- )
951 dst \ f type-number %load-immediate
952 0 "end" get branch1 execute( n addr -- )
953 branch2 [ 0 "end" get branch2 execute( n addr -- ) ] when
954 dst \ t %load-reference
955 "end" get resolve-label ; inline
957 :: %boolean ( dst cc temp -- )
958 cc negate-cc order-cc {
959 { cc< [ dst temp \ BLT f (%boolean) ] }
960 { cc<= [ dst temp \ BLE f (%boolean) ] }
961 { cc> [ dst temp \ BGT f (%boolean) ] }
962 { cc>= [ dst temp \ BGE f (%boolean) ] }
963 { cc= [ dst temp \ BEQ f (%boolean) ] }
964 { cc/= [ dst temp \ BNE f (%boolean) ] }
967 : (%compare) ( src1 src2 -- ) [ 0 ] 2dip %compare-cell ; inline
969 : (%compare-integer-imm) ( src1 src2 -- )
970 [ 0 ] 2dip %compare-cell-imm ; inline
972 : (%compare-imm) ( src1 src2 -- )
973 [ tag-fixnum ] [ \ f type-number ] if* (%compare-integer-imm) ; inline
975 : (%compare-float-unordered) ( src1 src2 -- )
976 [ 0 ] 2dip FCMPU ; inline
978 : (%compare-float-ordered) ( src1 src2 -- )
979 [ 0 ] 2dip FCMPO ; inline
981 :: (%compare-float) ( src1 src2 cc compare -- branch1 branch2 )
983 { cc< [ src1 src2 \ compare execute( a b -- ) \ BLT f ] }
984 { cc<= [ src1 src2 \ compare execute( a b -- ) \ BLT \ BEQ ] }
985 { cc> [ src1 src2 \ compare execute( a b -- ) \ BGT f ] }
986 { cc>= [ src1 src2 \ compare execute( a b -- ) \ BGT \ BEQ ] }
987 { cc= [ src1 src2 \ compare execute( a b -- ) \ BEQ f ] }
988 { cc<> [ src1 src2 \ compare execute( a b -- ) \ BLT \ BGT ] }
989 { cc<>= [ src1 src2 \ compare execute( a b -- ) \ BNS f ] }
990 { cc/< [ src1 src2 \ compare execute( a b -- ) \ BGE f ] }
991 { cc/<= [ src1 src2 \ compare execute( a b -- ) \ BGT \ BSO ] }
992 { cc/> [ src1 src2 \ compare execute( a b -- ) \ BLE f ] }
993 { cc/>= [ src1 src2 \ compare execute( a b -- ) \ BLT \ BSO ] }
994 { cc/= [ src1 src2 \ compare execute( a b -- ) \ BNE f ] }
995 { cc/<> [ src1 src2 \ compare execute( a b -- ) \ BEQ \ BSO ] }
996 { cc/<>= [ src1 src2 \ compare execute( a b -- ) \ BSO f ] }
999 M: ppc %compare [ (%compare) ] 2dip %boolean ;
1001 M: ppc %compare-imm [ (%compare-imm) ] 2dip %boolean ;
1003 M: ppc %compare-integer-imm [ (%compare-integer-imm) ] 2dip %boolean ;
1005 M:: ppc %compare-float-ordered ( dst src1 src2 cc temp -- )
1006 src1 src2 cc negate-cc \ (%compare-float-ordered) (%compare-float) :> ( branch1 branch2 )
1007 dst temp branch1 branch2 (%boolean) ;
1009 M:: ppc %compare-float-unordered ( dst src1 src2 cc temp -- )
1010 src1 src2 cc negate-cc \ (%compare-float-unordered) (%compare-float) :> ( branch1 branch2 )
1011 dst temp branch1 branch2 (%boolean) ;
1013 :: %branch ( label cc -- )
1015 { cc< [ 0 label BLT ] }
1016 { cc<= [ 0 label BLE ] }
1017 { cc> [ 0 label BGT ] }
1018 { cc>= [ 0 label BGE ] }
1019 { cc= [ 0 label BEQ ] }
1020 { cc/= [ 0 label BNE ] }
1023 M:: ppc %compare-branch ( label src1 src2 cc -- )
1024 src1 src2 (%compare)
1027 M:: ppc %compare-imm-branch ( label src1 src2 cc -- )
1028 src1 src2 (%compare-imm)
1031 M:: ppc %compare-integer-imm-branch ( label src1 src2 cc -- )
1032 src1 src2 (%compare-integer-imm)
1035 :: (%branch) ( label branch1 branch2 -- )
1036 0 label branch1 execute( cr label -- )
1037 branch2 [ 0 label branch2 execute( cr label -- ) ] when ; inline
1039 M:: ppc %compare-float-ordered-branch ( label src1 src2 cc -- )
1040 src1 src2 cc \ (%compare-float-ordered) (%compare-float) :> ( branch1 branch2 )
1041 label branch1 branch2 (%branch) ;
1043 M:: ppc %compare-float-unordered-branch ( label src1 src2 cc -- )
1044 src1 src2 cc \ (%compare-float-unordered) (%compare-float) :> ( branch1 branch2 )
1045 label branch1 branch2 (%branch) ;
1047 M: ppc %spill ( src rep dst -- )
1049 { int-rep [ [ 1 ] dip %store-cell ] }
1050 { tagged-rep [ [ 1 ] dip %store-cell ] }
1051 { float-rep [ [ 1 ] dip STFS ] }
1052 { double-rep [ [ 1 ] dip STFD ] }
1053 { vector-rep [ scratch-reg swap LI 1 scratch-reg STVX ] }
1054 { scalar-rep [ scratch-reg swap LI 1 scratch-reg STVX ] }
1057 M: ppc %reload ( dst rep src -- )
1059 { int-rep [ [ 1 ] dip %load-cell ] }
1060 { tagged-rep [ [ 1 ] dip %load-cell ] }
1061 { float-rep [ [ 1 ] dip LFS ] }
1062 { double-rep [ [ 1 ] dip LFD ] }
1063 { vector-rep [ scratch-reg swap LI 1 scratch-reg LVX ] }
1064 { scalar-rep [ scratch-reg swap LI 1 scratch-reg LVX ] }
1067 M: ppc %loop-entry ( -- ) ;
1068 M: ppc immediate-arithmetic? ( n -- ? ) -32768 32767 between? ;
1069 M: ppc immediate-bitwise? ( n -- ? ) 0 65535 between? ;
1070 M: ppc immediate-store? ( n -- ? ) immediate-comparand? ;
1076 { [ cpu ppc.32? ] [ "cpu.ppc.32.linux" require ] }
1077 { [ cpu ppc.64? ] [ "cpu.ppc.64.linux" require ] }
1084 complex-double lookup-c-type t >>return-in-registers? drop