1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien alien.accessors alien.c-types arrays cpu.ppc.assembler
4 cpu.ppc.architecture cpu.ppc.allot cpu.architecture kernel
5 kernel.private math math.private namespaces sequences words
6 generic quotations byte-arrays hashtables hashtables.private
7 generator generator.registers generator.fixup sequences.private
8 sbufs vectors system layouts math.floats.private
9 classes classes.tuple classes.tuple.private sbufs.private
10 vectors.private strings.private slots.private combinators
11 bit-arrays float-arrays compiler.constants ;
12 IN: cpu.ppc.intrinsics
14 : %slot-literal-known-tag
18 "obj" get operand-tag - ;
20 : %slot-literal-any-tag
21 "obj" operand "scratch1" operand %untag
22 "val" operand "scratch1" operand "n" get cells ;
25 "obj" operand "scratch1" operand %untag
26 "offset" operand "n" operand 1 SRAWI
27 "scratch1" operand "val" operand "offset" operand ;
30 ! Slot number is literal and the tag is known
32 [ %slot-literal-known-tag LWZ ] H{
33 { +input+ { { f "obj" known-tag } { [ small-slot? ] "n" } } }
34 { +scratch+ { { f "val" } } }
35 { +output+ { "val" } }
38 ! Slot number is literal
40 [ %slot-literal-any-tag LWZ ] H{
41 { +input+ { { f "obj" } { [ small-slot? ] "n" } } }
42 { +scratch+ { { f "scratch1" } { f "val" } } }
43 { +output+ { "val" } }
46 ! Slot number in a register
49 { +input+ { { f "obj" } { f "n" } } }
50 { +scratch+ { { f "val" } { f "scratch1" } { f "offset" } } }
51 { +output+ { "val" } }
56 : load-cards-offset ( dest -- )
57 "cards_offset" f pick %load-dlsym dup 0 LWZ ;
59 : load-decks-offset ( dest -- )
60 "decks_offset" f pick %load-dlsym dup 0 LWZ ;
62 : %write-barrier ( -- )
63 "val" get operand-immediate? "obj" get fresh-object? or [
64 card-mark "scratch1" operand LI
67 "val" operand load-cards-offset
68 "obj" operand "scratch2" operand card-bits SRWI
69 "scratch2" operand "scratch1" operand "val" operand STBX
72 "val" operand load-decks-offset
73 "obj" operand "scratch2" operand deck-bits SRWI
74 "scratch2" operand "scratch1" operand "val" operand STBX
78 ! Slot number is literal and tag is known
80 [ %slot-literal-known-tag STW %write-barrier ] H{
81 { +input+ { { f "val" } { f "obj" known-tag } { [ small-slot? ] "n" } } }
82 { +scratch+ { { f "scratch1" } { f "scratch2" } } }
83 { +clobber+ { "val" } }
86 ! Slot number is literal
88 [ %slot-literal-any-tag STW %write-barrier ] H{
89 { +input+ { { f "val" } { f "obj" } { [ small-slot? ] "n" } } }
90 { +scratch+ { { f "scratch1" } { f "scratch2" } } }
91 { +clobber+ { "val" } }
94 ! Slot number is in a register
96 [ %slot-any STWX %write-barrier ] H{
97 { +input+ { { f "val" } { f "obj" } { f "n" } } }
98 { +scratch+ { { f "scratch1" } { f "scratch2" } { f "offset" } } }
99 { +clobber+ { "val" } }
104 : fixnum-register-op ( op -- pair )
105 [ "out" operand "y" operand "x" operand ] swap suffix H{
106 { +input+ { { f "x" } { f "y" } } }
107 { +scratch+ { { f "out" } } }
108 { +output+ { "out" } }
111 : fixnum-value-op ( op -- pair )
112 [ "out" operand "x" operand "y" operand ] swap suffix H{
113 { +input+ { { f "x" } { [ small-tagged? ] "y" } } }
114 { +scratch+ { { f "out" } } }
115 { +output+ { "out" } }
118 : define-fixnum-op ( word imm-op reg-op -- )
119 >r fixnum-value-op r> fixnum-register-op 2array
123 { fixnum+fast ADDI ADD }
124 { fixnum-fast SUBI SUBF }
125 { fixnum-bitand ANDI AND }
126 { fixnum-bitor ORI OR }
127 { fixnum-bitxor XORI XOR }
129 first3 define-fixnum-op
135 "out" operand "x" operand "y" get MULLI
137 { +input+ { { f "x" } { [ small-tagged? ] "y" } } }
138 { +scratch+ { { f "out" } } }
139 { +output+ { "out" } }
143 "out" operand "x" operand %untag-fixnum
144 "out" operand "y" operand "out" operand MULLW
146 { +input+ { { f "x" } { f "y" } } }
147 { +scratch+ { { f "out" } } }
148 { +output+ { "out" } }
153 : %untag-fixnums ( seq -- )
154 [ dup %untag-fixnum ] unique-operands ;
156 \ fixnum-shift-fast {
159 "out" operand "x" operand "y" get
160 dup 0 < [ neg SRAWI ] [ swapd SLWI ] if
162 "out" operand dup %untag
164 { +input+ { { f "x" } { [ ] "y" } } }
165 { +scratch+ { { f "out" } } }
166 { +output+ { "out" } }
171 { "positive" "end" } [ define-label ] each
172 "out" operand "y" operand %untag-fixnum
175 "out" operand dup NEG
176 "out" operand "x" operand "out" operand SRAW
178 "positive" resolve-label
179 "out" operand "x" operand "out" operand SLW
182 "out" operand dup %untag
184 { +input+ { { f "x" } { f "y" } } }
185 { +scratch+ { { f "out" } } }
186 { +output+ { "out" } }
191 : generate-fixnum-mod
192 #! PowerPC doesn't have a MOD instruction; so we compute
193 #! x-(x/y)*y. Puts the result in "s" operand.
194 "s" operand "r" operand "y" operand MULLW
195 "s" operand "s" operand "x" operand SUBF ;
198 ! divide x by y, store result in x
199 "r" operand "x" operand "y" operand DIVW
202 { +input+ { { f "x" } { f "y" } } }
203 { +scratch+ { { f "r" } { f "s" } } }
209 "x" operand dup %untag
211 { +input+ { { f "x" } } }
215 : fixnum-register-jump ( op -- pair )
216 [ "x" operand 0 "y" operand CMP ] swap suffix
217 { { f "x" } { f "y" } } 2array ;
219 : fixnum-value-jump ( op -- pair )
220 [ 0 "x" operand "y" operand CMPI ] swap suffix
221 { { f "x" } { [ small-tagged? ] "y" } } 2array ;
223 : define-fixnum-jump ( word op -- )
224 [ fixnum-value-jump ] keep fixnum-register-jump
225 2array define-if-intrinsics ;
234 first2 define-fixnum-jump
237 : overflow-check ( insn1 insn2 -- )
241 "r" operand "y" operand "x" operand r> execute
245 { "x" "y" } %untag-fixnums
246 "r" operand "y" operand "x" operand r> execute
247 "r" get %allot-bignum-signed-1
249 ] with-scope ; inline
251 : overflow-template ( word insn1 insn2 -- )
252 [ overflow-check ] 2curry H{
253 { +input+ { { f "x" } { f "y" } } }
254 { +scratch+ { { f "r" } } }
256 { +clobber+ { "x" "y" } }
259 \ fixnum+ \ ADD \ ADDO. overflow-template
260 \ fixnum- \ SUBF \ SUBFO. overflow-template
263 #! This VOP is funny. If there is an overflow, it falls
264 #! through to the end, and the result is in "x" operand.
265 #! Otherwise it jumps to the "no-overflow" label and the
266 #! result is in "r" operand.
268 "no-overflow" define-label
269 "r" operand "x" operand "y" operand DIVW
270 ! if the result is greater than the most positive fixnum,
271 ! which can only ever happen if we do
272 ! most-negative-fixnum -1 /i, then the result is a bignum.
273 most-positive-fixnum "s" operand LOAD
274 "r" operand 0 "s" operand CMP
275 "no-overflow" get BLE
276 most-negative-fixnum neg "x" operand LOAD
277 "x" get %allot-bignum-signed-1 ;
282 "no-overflow" resolve-label
283 "r" operand "x" operand %tag-fixnum
286 { +input+ { { f "x" } { f "y" } } }
287 { +scratch+ { { f "r" } { f "s" } } }
289 { +clobber+ { "y" } }
296 "no-overflow" resolve-label
298 "r" operand "x" operand %tag-fixnum
301 { +input+ { { f "x" } { f "y" } } }
302 { +scratch+ { { f "r" } { f "s" } } }
303 { +output+ { "x" "s" } }
304 { +clobber+ { "y" } }
308 "x" operand dup %untag-fixnum
309 "x" get %allot-bignum-signed-1
311 { +input+ { { f "x" } } }
316 "nonzero" define-label
317 "positive" define-label
319 "x" operand dup %untag
320 "y" operand "x" operand cell LWZ
321 ! if the length is 1, its just the sign and nothing else,
323 0 "y" operand 1 v>operand CMPI
327 "nonzero" resolve-label
329 "y" operand "x" operand 3 cells LWZ
331 "x" operand "x" operand 2 cells LWZ
332 ! is the sign negative?
335 "y" operand dup -1 MULI
336 "positive" resolve-label
337 "y" operand dup %tag-fixnum
340 { +input+ { { f "x" } } }
341 { +scratch+ { { f "y" } } }
342 { +clobber+ { "x" } }
346 : define-float-op ( word op -- )
347 [ "z" operand "x" operand "y" operand ] swap suffix H{
348 { +input+ { { float "x" } { float "y" } } }
349 { +scratch+ { { float "z" } } }
359 first2 define-float-op
362 : define-float-jump ( word op -- )
363 [ "x" operand 0 "y" operand FCMPU ] swap suffix
364 { { float "x" } { float "y" } } define-if-intrinsic ;
373 first2 define-float-jump
377 "scratch" operand "in" operand FCTIWZ
378 "scratch" operand 1 0 param@ STFD
379 "out" operand 1 cell param@ LWZ
380 "out" operand dup %tag-fixnum
382 { +input+ { { float "in" } } }
383 { +scratch+ { { float "scratch" } { f "out" } } }
384 { +output+ { "out" } }
388 HEX: 4330 "scratch" operand LIS
389 "scratch" operand 1 0 param@ STW
390 "scratch" operand "in" operand %untag-fixnum
391 "scratch" operand dup HEX: 8000 XORIS
392 "scratch" operand 1 cell param@ STW
393 "f1" operand 1 0 param@ LFD
394 4503601774854144.0 "scratch" operand load-indirect
395 "f2" operand "scratch" operand float-offset LFD
396 "f1" operand "f1" operand "f2" operand FSUB
398 { +input+ { { f "in" } } }
399 { +scratch+ { { f "scratch" } { float "f1" } { float "f2" } } }
400 { +output+ { "f1" } }
405 "out" operand "in" operand tag-mask get ANDI
406 "out" operand dup %tag-fixnum
408 { +input+ { { f "in" } } }
409 { +scratch+ { { f "out" } } }
410 { +output+ { "out" } }
414 #! Load the userenv pointer in a register.
415 "userenv" f rot %load-dlsym ;
418 "n" operand dup 1 SRAWI
420 "x" operand "n" operand "x" operand ADD
421 "x" operand dup 0 LWZ
423 { +input+ { { f "n" } } }
424 { +scratch+ { { f "x" } } }
426 { +clobber+ { "n" } }
430 "n" operand dup 1 SRAWI
432 "x" operand "n" operand "x" operand ADD
433 "val" operand "x" operand 0 STW
435 { +input+ { { f "val" } { f "n" } } }
436 { +scratch+ { { f "x" } } }
437 { +clobber+ { "n" } }
441 tuple "layout" get layout-size 2 + cells %allot
443 "layout" get 12 load-indirect
445 ! Zero out the rest of the tuple
447 "layout" get layout-size [ 12 11 rot 2 + cells STW ] each
448 ! Store tagged ptr in reg
449 "tuple" get tuple %store-tagged
451 { +input+ { { [ tuple-layout? ] "layout" } } }
452 { +scratch+ { { f "tuple" } } }
453 { +output+ { "tuple" } }
457 array "n" get 2 + cells %allot
461 ! Store initial element
462 "n" get [ "initial" operand 11 rot 2 + cells STW ] each
463 ! Store tagged ptr in reg
464 "array" get object %store-tagged
466 { +input+ { { [ inline-array? ] "n" } { f "initial" } } }
467 { +scratch+ { { f "array" } } }
468 { +output+ { "array" } }
472 byte-array "n" get 2 cells + %allot
476 ! Store initial element
478 "n" get cell align cell /i [ 12 11 rot 2 + cells STW ] each
479 ! Store tagged ptr in reg
480 "array" get object %store-tagged
482 { +input+ { { [ inline-array? ] "n" } } }
483 { +scratch+ { { f "array" } } }
484 { +output+ { "array" } }
489 "numerator" operand 11 1 cells STW
490 "denominator" operand 11 2 cells STW
491 ! Store tagged ptr in reg
492 "ratio" get ratio %store-tagged
494 { +input+ { { f "numerator" } { f "denominator" } } }
495 { +scratch+ { { f "ratio" } } }
496 { +output+ { "ratio" } }
500 complex 3 cells %allot
501 "real" operand 11 1 cells STW
502 "imaginary" operand 11 2 cells STW
503 ! Store tagged ptr in reg
504 "complex" get complex %store-tagged
506 { +input+ { { f "real" } { f "imaginary" } } }
507 { +scratch+ { { f "complex" } } }
508 { +output+ { "complex" } }
512 wrapper 2 cells %allot
513 "obj" operand 11 1 cells STW
514 ! Store tagged ptr in reg
515 "wrapper" get object %store-tagged
517 { +input+ { { f "obj" } } }
518 { +scratch+ { { f "wrapper" } } }
519 { +output+ { "wrapper" } }
523 : %alien-accessor ( quot -- )
524 "offset" operand dup %untag-fixnum
525 "offset" operand dup "alien" operand ADD
526 "value" operand "offset" operand 0 roll call ; inline
528 : alien-integer-get-template
531 { unboxed-c-ptr "alien" c-ptr }
532 { f "offset" fixnum }
534 { +scratch+ { { f "value" } } }
535 { +output+ { "value" } }
536 { +clobber+ { "offset" } }
539 : %alien-integer-get ( quot -- )
541 "value" operand dup %tag-fixnum ; inline
543 : alien-integer-set-template
547 { unboxed-c-ptr "alien" c-ptr }
548 { f "offset" fixnum }
550 { +clobber+ { "value" "offset" } }
553 : %alien-integer-set ( quot -- )
554 "offset" get "value" get = [
555 "value" operand dup %untag-fixnum
557 %alien-accessor ; inline
559 : define-alien-integer-intrinsics ( word get-quot word set-quot -- )
560 [ %alien-integer-set ] curry
561 alien-integer-set-template
563 [ %alien-integer-get ] curry
564 alien-integer-get-template
567 \ alien-unsigned-1 [ LBZ ]
568 \ set-alien-unsigned-1 [ STB ]
569 define-alien-integer-intrinsics
571 \ alien-signed-1 [ pick >r LBZ r> dup EXTSB ]
572 \ set-alien-signed-1 [ STB ]
573 define-alien-integer-intrinsics
575 \ alien-unsigned-2 [ LHZ ]
576 \ set-alien-unsigned-2 [ STH ]
577 define-alien-integer-intrinsics
579 \ alien-signed-2 [ LHA ]
580 \ set-alien-signed-2 [ STH ]
581 define-alien-integer-intrinsics
584 [ LWZ ] %alien-accessor
587 { unboxed-c-ptr "alien" c-ptr }
588 { f "offset" fixnum }
590 { +scratch+ { { unboxed-alien "value" } } }
591 { +output+ { "value" } }
592 { +clobber+ { "offset" } }
596 [ STW ] %alien-accessor
599 { unboxed-c-ptr "value" pinned-c-ptr }
600 { unboxed-c-ptr "alien" c-ptr }
601 { f "offset" fixnum }
603 { +clobber+ { "offset" } }
606 : alien-float-get-template
609 { unboxed-c-ptr "alien" c-ptr }
610 { f "offset" fixnum }
612 { +scratch+ { { float "value" } } }
613 { +output+ { "value" } }
614 { +clobber+ { "offset" } }
617 : alien-float-set-template
620 { float "value" float }
621 { unboxed-c-ptr "alien" c-ptr }
622 { f "offset" fixnum }
624 { +clobber+ { "offset" } }
627 : define-alien-float-intrinsics ( word get-quot word set-quot -- )
628 [ %alien-accessor ] curry
629 alien-float-set-template
631 [ %alien-accessor ] curry
632 alien-float-get-template
635 \ alien-double [ LFD ]
636 \ set-alien-double [ STFD ]
637 define-alien-float-intrinsics
639 \ alien-float [ LFS ]
640 \ set-alien-float [ STFS ]
641 define-alien-float-intrinsics