1 ! Copyright (C) 2005, 2007 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien 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.functions math.floats.private
9 classes tuples tuples.private sbufs.private vectors.private
10 strings.private slots.private combinators bit-arrays
12 IN: cpu.ppc.intrinsics
14 : %slot-literal-known-tag
20 : %slot-literal-any-tag
21 "obj" operand "scratch" operand %untag
22 "val" operand "scratch" operand "n" get cells ;
25 "obj" operand "scratch" operand %untag
26 "n" operand dup 1 SRAWI
27 "scratch" operand "val" operand "n" 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 "scratch" } { f "val" } } }
43 { +output+ { "val" } }
46 ! Slot number in a register
49 { +input+ { { f "obj" } { f "n" } } }
50 { +scratch+ { { f "val" } { f "scratch" } } }
51 { +output+ { "val" } }
57 : load-cards-offset ( dest -- )
58 "cards_offset" f pick %load-dlsym dup 0 LWZ ;
60 : %write-barrier ( -- )
61 "val" operand-immediate? "obj" get fresh-object? or [
62 "obj" operand "scratch" operand card-bits SRWI
63 "val" operand load-cards-offset
64 "scratch" operand dup "val" operand ADD
65 "val" operand "scratch" operand 0 LBZ
66 "val" operand dup card-mark ORI
67 "val" operand "scratch" operand 0 STB
71 ! Slot number is literal and tag is known
73 [ %slot-literal-known-tag STW %write-barrier ] H{
74 { +input+ { { f "val" } { f "obj" known-tag } { [ small-slot? ] "n" } } }
75 { +scratch+ { { f "scratch" } } }
76 { +clobber+ { "val" } }
79 ! Slot number is literal
81 [ %slot-literal-any-tag STW %write-barrier ] H{
82 { +input+ { { f "val" } { f "obj" } { [ small-slot? ] "n" } } }
83 { +scratch+ { { f "scratch" } } }
84 { +clobber+ { "val" } }
87 ! Slot number is in a register
89 [ %slot-any STWX %write-barrier ] H{
90 { +input+ { { f "val" } { f "obj" } { f "n" } } }
91 { +scratch+ { { f "scratch" } } }
92 { +clobber+ { "val" "n" } }
98 "out" operand "obj" operand MR
99 "n" operand dup 2 SRAWI
100 "n" operand "obj" operand "n" operand ADD
101 "out" operand "n" operand string-offset LHZ
102 "out" operand dup %tag-fixnum
104 { +input+ { { f "n" } { f "obj" } } }
105 { +scratch+ { { f "out" } } }
106 { +output+ { "out" } }
107 { +clobber+ { "n" } }
111 "val" operand dup %untag-fixnum
112 "slot" operand dup 2 SRAWI
113 "slot" operand dup "obj" operand ADD
114 "val" operand "slot" operand string-offset STH
116 { +input+ { { f "val" } { f "slot" } { f "obj" } } }
117 { +clobber+ { "val" "slot" } }
120 : fixnum-register-op ( op -- pair )
121 [ "out" operand "y" operand "x" operand ] swap add H{
122 { +input+ { { f "x" } { f "y" } } }
123 { +scratch+ { { f "out" } } }
124 { +output+ { "out" } }
127 : fixnum-value-op ( op -- pair )
128 [ "out" operand "x" operand "y" operand ] swap add H{
129 { +input+ { { f "x" } { [ small-tagged? ] "y" } } }
130 { +scratch+ { { f "out" } } }
131 { +output+ { "out" } }
134 : define-fixnum-op ( word imm-op reg-op -- )
135 >r fixnum-value-op r> fixnum-register-op 2array
139 { fixnum+fast ADDI ADD }
140 { fixnum-fast SUBI SUBF }
141 { fixnum-bitand ANDI AND }
142 { fixnum-bitor ORI OR }
143 { fixnum-bitxor XORI XOR }
145 first3 define-fixnum-op
151 "out" operand "x" operand "y" get MULLI
153 { +input+ { { f "x" } { [ small-tagged? ] "y" } } }
154 { +scratch+ { { f "out" } } }
155 { +output+ { "out" } }
159 "out" operand "x" operand %untag-fixnum
160 "out" operand "y" operand "out" operand MULLW
162 { +input+ { { f "x" } { f "y" } } }
163 { +scratch+ { { f "out" } } }
164 { +output+ { "out" } }
170 "out" operand "x" operand "y" get neg SRAWI
172 "out" operand dup %untag
174 { +input+ { { f "x" } { [ -31 0 between? ] "y" } } }
175 { +scratch+ { { f "out" } } }
176 { +output+ { "out" } }
179 : generate-fixnum-mod
180 #! PowerPC doesn't have a MOD instruction; so we compute
181 #! x-(x/y)*y. Puts the result in "s" operand.
182 "s" operand "r" operand "y" operand MULLW
183 "s" operand "s" operand "x" operand SUBF ;
186 ! divide x by y, store result in x
187 "r" operand "x" operand "y" operand DIVW
190 { +input+ { { f "x" } { f "y" } } }
191 { +scratch+ { { f "r" } { f "s" } } }
197 "x" operand dup %untag
199 { +input+ { { f "x" } } }
203 : fixnum-register-jump ( op -- pair )
204 [ "x" operand 0 "y" operand CMP ] swap add
205 { { f "x" } { f "y" } } 2array ;
207 : fixnum-value-jump ( op -- pair )
208 [ 0 "x" operand "y" operand CMPI ] swap add
209 { { f "x" } { [ small-tagged? ] "y" } } 2array ;
211 : define-fixnum-jump ( word op -- )
212 [ fixnum-value-jump ] keep fixnum-register-jump
213 2array define-if-intrinsics ;
222 first2 define-fixnum-jump
225 : %untag-fixnums ( seq -- )
226 [ dup %untag-fixnum ] unique-operands ;
228 : overflow-check ( insn1 insn2 -- )
232 "r" operand "y" operand "x" operand r> execute
236 { "x" "y" } %untag-fixnums
237 "r" operand "y" operand "x" operand r> execute
238 "r" get %allot-bignum-signed-1
240 ] with-scope ; inline
242 : overflow-template ( word insn1 insn2 -- )
243 [ overflow-check ] 2curry H{
244 { +input+ { { f "x" } { f "y" } } }
245 { +scratch+ { { f "r" } } }
247 { +clobber+ { "x" "y" } }
250 \ fixnum+ \ ADD \ ADDO. overflow-template
251 \ fixnum- \ SUBF \ SUBFO. overflow-template
254 #! This VOP is funny. If there is an overflow, it falls
255 #! through to the end, and the result is in "x" operand.
256 #! Otherwise it jumps to the "no-overflow" label and the
257 #! result is in "r" operand.
259 "no-overflow" define-label
260 "r" operand "x" operand "y" operand DIVW
261 ! if the result is greater than the most positive fixnum,
262 ! which can only ever happen if we do
263 ! most-negative-fixnum -1 /i, then the result is a bignum.
264 most-positive-fixnum "s" operand LOAD
265 "r" operand 0 "s" operand CMP
266 "no-overflow" get BLE
267 most-negative-fixnum neg "x" operand LOAD
268 "x" get %allot-bignum-signed-1 ;
273 "no-overflow" resolve-label
274 "r" operand "x" operand %tag-fixnum
277 { +input+ { { f "x" } { f "y" } } }
278 { +scratch+ { { f "r" } { f "s" } } }
280 { +clobber+ { "y" } }
287 "no-overflow" resolve-label
289 "r" operand "x" operand %tag-fixnum
292 { +input+ { { f "x" } { f "y" } } }
293 { +scratch+ { { f "r" } { f "s" } } }
294 { +output+ { "x" "s" } }
295 { +clobber+ { "y" } }
299 "x" operand dup %untag-fixnum
300 "x" get %allot-bignum-signed-1
302 { +input+ { { f "x" } } }
307 "nonzero" define-label
308 "positive" define-label
310 "x" operand dup %untag
311 "y" operand "x" operand cell LWZ
312 ! if the length is 1, its just the sign and nothing else,
314 0 "y" operand 1 v>operand CMPI
318 "nonzero" resolve-label
320 "y" operand "x" operand 3 cells LWZ
322 "x" operand "x" operand 2 cells LWZ
323 ! is the sign negative?
326 "y" operand dup -1 MULI
327 "positive" resolve-label
328 "y" operand dup %tag-fixnum
331 { +input+ { { f "x" } } }
332 { +scratch+ { { f "y" } } }
333 { +clobber+ { "x" } }
337 : define-float-op ( word op -- )
338 [ "x" operand "x" operand "y" operand ] swap add H{
339 { +input+ { { float "x" } { float "y" } } }
349 first2 define-float-op
352 : define-float-jump ( word op -- )
353 [ "x" operand 0 "y" operand FCMPU ] swap add
354 { { float "x" } { float "y" } } define-if-intrinsic ;
363 first2 define-float-jump
367 "scratch" operand "in" operand FCTIWZ
368 "scratch" operand 1 0 param@ STFD
369 "out" operand 1 cell param@ LWZ
370 "out" operand dup %tag-fixnum
372 { +input+ { { float "in" } } }
373 { +scratch+ { { float "scratch" } { f "out" } } }
374 { +output+ { "out" } }
378 ! "y" operand "x" operand FSQRT
380 ! { +input+ { { float "x" } } }
381 ! { +scratch+ { { float "y" } } }
382 ! { +output+ { "y" } }
386 "out" operand "in" operand tag-mask get ANDI
387 "out" operand dup %tag-fixnum
389 { +input+ { { f "in" } } }
390 { +scratch+ { { f "out" } } }
391 { +output+ { "out" } }
397 "y" operand "obj" operand tag-mask get ANDI
399 "y" operand "x" operand %tag-fixnum
400 ! Compare with object tag number (3).
401 0 "y" operand object tag-number CMPI
402 ! Jump if the object doesn't store type info in its header
404 ! It does store type info in its header
405 "x" operand "obj" operand header-offset LWZ
408 { +input+ { { f "obj" } } }
409 { +scratch+ { { f "x" } { f "y" } } }
416 "object" define-label
418 "y" operand "obj" operand tag-mask get ANDI
419 ! Compare with tuple tag number (2).
420 0 "y" operand tuple tag-number CMPI
422 ! Compare with object tag number (3).
423 0 "y" operand object tag-number CMPI
426 "y" operand "x" operand %tag-fixnum
428 "object" get resolve-label
430 "x" operand "obj" operand header-offset LWZ
432 "tuple" get resolve-label
434 "x" operand "obj" operand tuple-class-offset LWZ
435 "x" operand dup class-hash-offset LWZ
438 { +input+ { { f "obj" } } }
439 { +scratch+ { { f "x" } { f "y" } } }
444 #! Load the userenv pointer in a register.
445 "userenv" f rot %load-dlsym ;
448 "n" operand dup 1 SRAWI
450 "x" operand "n" operand "x" operand ADD
451 "x" operand dup 0 LWZ
453 { +input+ { { f "n" } } }
454 { +scratch+ { { f "x" } } }
456 { +clobber+ { "n" } }
460 "n" operand dup 1 SRAWI
462 "x" operand "n" operand "x" operand ADD
463 "val" operand "x" operand 0 STW
465 { +input+ { { f "val" } { f "n" } } }
466 { +scratch+ { { f "x" } } }
467 { +clobber+ { "n" } }
471 tuple "n" get 2 + cells %allot
476 "class" operand 11 2 cells STW
477 ! Zero out the rest of the tuple
479 "n" get 1- [ 12 11 rot 3 + cells STW ] each
480 ! Store tagged ptr in reg
481 "tuple" get tuple %store-tagged
483 { +input+ { { f "class" } { [ inline-array? ] "n" } } }
484 { +scratch+ { { f "tuple" } } }
485 { +output+ { "tuple" } }
489 array "n" get 2 + cells %allot
493 ! Store initial element
494 "n" get [ "initial" operand 11 rot 2 + cells STW ] each
495 ! Store tagged ptr in reg
496 "array" get object %store-tagged
498 { +input+ { { [ inline-array? ] "n" } { f "initial" } } }
499 { +scratch+ { { f "array" } } }
500 { +output+ { "array" } }
504 byte-array "n" get 2 cells + %allot
508 ! Store initial element
510 "n" get cell align cell /i [ 12 11 rot 2 + cells STW ] each
511 ! Store tagged ptr in reg
512 "array" get object %store-tagged
514 { +input+ { { [ inline-array? ] "n" } } }
515 { +scratch+ { { f "array" } } }
516 { +output+ { "array" } }
521 "numerator" operand 11 1 cells STW
522 "denominator" operand 11 2 cells STW
523 ! Store tagged ptr in reg
524 "ratio" get ratio %store-tagged
526 { +input+ { { f "numerator" } { f "denominator" } } }
527 { +scratch+ { { f "ratio" } } }
528 { +output+ { "ratio" } }
532 complex 3 cells %allot
533 "real" operand 11 1 cells STW
534 "imaginary" operand 11 2 cells STW
535 ! Store tagged ptr in reg
536 "complex" get complex %store-tagged
538 { +input+ { { f "real" } { f "imaginary" } } }
539 { +scratch+ { { f "complex" } } }
540 { +output+ { "complex" } }
544 wrapper 2 cells %allot
545 "obj" operand 11 1 cells STW
546 ! Store tagged ptr in reg
547 "wrapper" get object %store-tagged
549 { +input+ { { f "obj" } } }
550 { +scratch+ { { f "wrapper" } } }
551 { +output+ { "wrapper" } }
555 hashtable 4 cells %allot
560 ! Store tagged ptr in reg
561 "hashtable" get object %store-tagged
563 { +scratch+ { { f "hashtable" } } }
564 { +output+ { "hashtable" } }
569 "length" operand 11 1 cells STW
570 "string" operand 11 2 cells STW
571 ! Store tagged ptr in reg
572 "sbuf" get object %store-tagged
574 { +input+ { { f "string" } { f "length" } } }
575 { +scratch+ { { f "sbuf" } } }
576 { +output+ { "sbuf" } }
580 vector 3 cells %allot
581 "length" operand 11 1 cells STW
582 "array" operand 11 2 cells STW
583 ! Store tagged ptr in reg
584 "vector" get object %store-tagged
586 { +input+ { { f "array" } { f "length" } } }
587 { +scratch+ { { f "vector" } } }
588 { +output+ { "vector" } }
592 \ curry 3 cells %allot
593 "obj" operand 11 1 cells STW
594 "quot" operand 11 2 cells STW
595 ! Store tagged ptr in reg
596 "curry" get object %store-tagged
598 { +input+ { { f "obj" } { f "quot" } } }
599 { +scratch+ { { f "curry" } } }
600 { +output+ { "curry" } }
604 : alien-integer-get-template
607 { f "alien" simple-c-ptr }
608 { f "offset" fixnum }
610 { +scratch+ { { f "output" } } }
611 { +output+ { "output" } }
612 { +clobber+ { "offset" } }
615 : %alien-get ( quot -- )
616 "output" get "address" set
617 "offset" operand dup %untag-fixnum
618 "output" operand "alien" operand-class %alien-accessor ;
620 : %alien-integer-get ( quot -- )
622 "output" operand dup %tag-fixnum ; inline
624 : %alien-integer-set ( quot -- )
625 { "offset" "value" } %untag-fixnums
626 "value" operand "alien" operand-class %alien-accessor ; inline
628 : alien-integer-set-template
632 { f "alien" simple-c-ptr }
633 { f "offset" fixnum }
635 { +scratch+ { { f "address" } } }
636 { +clobber+ { "value" "offset" } }
639 : define-alien-integer-intrinsics ( word get-quot word set-quot -- )
640 [ %alien-integer-set ] curry
641 alien-integer-set-template
643 [ %alien-integer-get ] curry
644 alien-integer-get-template
647 \ alien-unsigned-1 [ LBZ ]
648 \ set-alien-unsigned-1 [ STB ]
649 define-alien-integer-intrinsics
651 \ alien-signed-1 [ pick >r LBZ r> dup EXTSB ]
652 \ set-alien-signed-1 [ STB ]
653 define-alien-integer-intrinsics
655 \ alien-unsigned-2 [ LHZ ]
656 \ set-alien-unsigned-2 [ STH ]
657 define-alien-integer-intrinsics
659 \ alien-signed-2 [ LHA ]
660 \ set-alien-signed-2 [ STH ]
661 define-alien-integer-intrinsics
663 : %alien-float-get ( quot -- )
664 "offset" operand dup %untag-fixnum
665 "output" operand "alien" operand-class %alien-accessor ; inline
667 : alien-float-get-template
670 { f "alien" simple-c-ptr }
671 { f "offset" fixnum }
673 { +scratch+ { { float "output" } { f "address" } } }
674 { +output+ { "output" } }
675 { +clobber+ { "offset" } }
678 : %alien-float-set ( quot -- )
679 "offset" operand dup %untag-fixnum
680 "value" operand "alien" operand-class %alien-accessor ; inline
682 : alien-float-set-template
685 { float "value" float }
686 { f "alien" simple-c-ptr }
687 { f "offset" fixnum }
689 { +scratch+ { { f "address" } } }
690 { +clobber+ { "offset" } }
693 : define-alien-float-intrinsics ( word get-quot word set-quot -- )
694 [ %alien-float-set ] curry
695 alien-float-set-template
697 [ %alien-float-get ] curry
698 alien-float-get-template
701 \ alien-double [ LFD ]
702 \ set-alien-double [ STFD ]
703 define-alien-float-intrinsics
705 \ alien-float [ LFS ]
706 \ set-alien-float [ STFS ]
707 define-alien-float-intrinsics
711 "output" get %allot-alien
712 ] alien-integer-get-template define-intrinsic