1 ! Copyright (C) 2005, 2006 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: alien assembler kernel kernel-internals math
5 math-internals namespaces sequences words ;
7 : generate-slot ( size quot -- )
9 ! turn tagged fixnum slot # into an offset, multiple of 4
10 "n" operand dup tag-bits r> - SRAWI
11 ! compute slot address
12 "obj" operand dup "n" operand ADD
14 "obj" operand dup r> call ; inline
17 "obj" operand dup %untag
18 cell log2 [ 0 LWZ ] generate-slot
20 { +input+ { { f "obj" } { f "n" } } }
21 { +output+ { "obj" } }
25 1 [ string-offset LHZ ] generate-slot
26 "obj" operand dup %tag-fixnum
28 { +input+ { { f "n" } { f "obj" } } }
29 { +output+ { "obj" } }
32 : generate-set-slot ( size quot -- )
34 ! turn tagged fixnum slot # into an offset, multiple of 4
35 "slot" operand dup tag-bits r> - SRAWI
36 ! compute slot address in 1st input
37 "slot" operand dup "obj" operand ADD
38 ! store new slot value
39 "val" operand "slot" operand r> call ; inline
41 : generate-write-barrier ( -- )
42 #! Mark the card pointed to by vreg.
43 "obj" operand dup card-bits SRAWI
44 "obj" operand dup 16 ADD
45 "x" operand "obj" operand 0 LBZ
46 "x" operand dup card-mark ORI
47 "x" operand "obj" operand 0 STB ;
50 "obj" operand dup %untag
51 cell log2 [ 0 STW ] generate-set-slot generate-write-barrier
53 { +input+ { { f "val" } { f "obj" } { f "slot" } } }
54 { +scratch+ { { f "x" } } }
55 { +clobber+ { "obj" "slot" } }
59 ! untag the new value in 0th input
60 "val" operand dup %untag-fixnum
61 1 [ string-offset STH ] generate-set-slot
63 { +input+ { { f "val" } { f "slot" } { f "obj" } } }
64 { +scratch+ { { f "x" } } }
65 { +clobber+ { "val" "slot" "obj" } }
68 : define-fixnum-op ( word op -- )
69 [ [ "x" operand "y" operand "x" operand ] % , ] [ ] make H{
70 { +input+ { { f "x" } { f "y" } } }
81 first2 define-fixnum-op
85 #! PowerPC doesn't have a MOD instruction; so we compute
86 #! x-(x/y)*y. Puts the result in "s" operand.
87 "s" operand "r" operand "y" operand MULLW
88 "s" operand "s" operand "x" operand SUBF ;
91 ! divide x by y, store result in x
92 "r" operand "x" operand "y" operand DIVW
95 { +input+ { { f "x" } { f "y" } } }
96 { +scratch+ { { f "r" } { f "s" } } }
102 "x" operand dup %untag
104 { +input+ { { f "x" } } }
108 : define-fixnum-jump ( word op -- )
109 [ "x" operand 0 "y" operand CMP ] swap add
110 { { f "x" } { f "y" } } define-if-intrinsic ;
119 first2 define-fixnum-jump
122 : simple-overflow ( word -- )
127 { "x" "y" } [ dup %untag-fixnum ] unique-operands
128 "r" operand "y" operand "x" operand r> execute
129 "r" operand %allot-bignum-signed-1
131 ] with-scope ; inline
135 "r" operand "y" operand "x" operand ADDO.
136 \ ADD simple-overflow
138 { +input+ { { f "x" } { f "y" } } }
139 { +scratch+ { { f "r" } } }
141 { +clobber+ { "x" "y" } }
146 "r" operand "y" operand "x" operand SUBFO.
147 \ SUBF simple-overflow
149 { +input+ { { f "x" } { f "y" } } }
150 { +scratch+ { { f "r" } } }
152 { +clobber+ { "x" "y" } }
157 ! "r" operand "x" operand %untag-fixnum
159 ! "s" operand "y" operand "r" operand MULLWO.
161 ! "s" operand "y" operand 1 SRAWI
162 ! "x" operand "s" operand "r" operand MULLWO.
163 ! "x" operand dup 2 SRAWI
164 ! "s" operand "s" operand "r" operand MULHW
165 ! "s" operand "x" operand %allot-bignum-signed-2
166 ! "end" resolve-label
168 ! { +input+ { { f "x" } { f "y" } } }
169 ! { +scratch+ { { f "r" } { f "s" } } }
170 ! { +output+ { "s" } }
171 ! { +clobber+ { "x" "y" } }
175 #! This VOP is funny. If there is an overflow, it falls
176 #! through to the end, and the result is in "x" operand.
177 #! Otherwise it jumps to the "no-overflow" label and the
178 #! result is in "r" operand.
180 "no-overflow" define-label
181 "r" operand "x" operand "y" operand DIVW
182 ! if the result is greater than the most positive fixnum,
183 ! which can only ever happen if we do
184 ! most-negative-fixnum -1 /i, then the result is a bignum.
185 most-positive-fixnum "s" operand LOAD
186 "r" operand 0 "s" operand CMP
187 "no-overflow" get BLE
188 most-negative-fixnum neg "x" operand LOAD
189 "x" operand %allot-bignum-signed-1 ;
194 "no-overflow" resolve-label
195 "r" operand "x" operand %tag-fixnum
198 { +input+ { { f "x" } { f "y" } } }
199 { +scratch+ { { f "r" } { f "s" } } }
201 { +clobber+ { "y" } }
208 "no-overflow" resolve-label
210 "r" operand "x" operand %tag-fixnum
213 { +input+ { { f "x" } { f "y" } } }
214 { +scratch+ { { f "r" } { f "s" } } }
215 { +output+ { "x" "s" } }
216 { +clobber+ { "y" } }
220 "nonzero" define-label
222 0 "x" operand 0 CMPI ! is it zero?
224 0 >bignum "x" get load-literal
226 "nonzero" resolve-label
227 "x" operand dup %untag-fixnum
228 "x" operand %allot-bignum-signed-1
231 { +input+ { { f "x" } } }
236 "nonzero" define-label
237 "positive" define-label
239 "x" operand dup %untag
240 "y" operand "x" operand cell LWZ
241 ! if the length is 1, its just the sign and nothing else,
243 0 "y" operand 1 tag-bits shift CMPI
247 "nonzero" resolve-label
249 "y" operand "x" operand 3 cells LWZ
251 "x" operand "x" operand 2 cells LWZ
252 ! is the sign negative?
255 "y" operand dup -1 MULI
256 "positive" resolve-label
257 "y" operand dup %tag-fixnum
260 { +input+ { { f "x" } } }
261 { +scratch+ { { f "y" } } }
262 { +clobber+ { "x" } }
266 : define-float-op ( word op -- )
267 [ [ "x" operand "x" operand "y" operand ] % , ] [ ] make H{
268 { +input+ { { float "x" } { float "y" } } }
278 first2 define-float-op
281 : define-float-jump ( word op -- )
282 [ "x" operand 0 "y" operand FCMPU ] swap add
283 { { float "x" } { float "y" } } define-if-intrinsic ;
292 first2 define-float-jump
296 "scratch" operand "in" operand FCTIWZ
297 "scratch" operand 1 0 stack@ STFD
298 "out" operand 1 cell stack@ LWZ
299 "out" operand dup %tag-fixnum
301 { +input+ { { float "in" } } }
302 { +scratch+ { { float "scratch" } { f "out" } } }
303 { +output+ { "out" } }
307 "in" operand "out" operand tag-mask ANDI
308 "out" operand dup %tag-fixnum
310 { +input+ { { f "in" } } }
311 { +scratch+ { { f "out" } } }
312 { +output+ { "out" } }
319 "obj" operand "y" operand tag-mask ANDI
321 "y" operand "x" operand %tag-fixnum
322 ! Compare with object tag number (3).
323 0 "y" operand object-tag CMPI
324 ! Jump if the object doesn't store type info in its header
326 ! It does store type info in its header
327 ! Is the pointer itself equal to 3? Then its F_TYPE (9).
328 0 "obj" operand object-tag CMPI
330 ! The pointer is not equal to 3. Load the object header.
331 "x" operand "obj" operand object-tag neg LWZ
332 "x" operand dup %untag
335 ! The pointer is equal to 3. Load F_TYPE (9).
336 f type tag-bits shift "x" operand LI
339 { +input+ { { f "obj" } } }
340 { +scratch+ { { f "x" } { f "y" } } }
345 #! Load the userenv pointer in a register.
346 "userenv" f rot compile-dlsym ;
349 "n" operand dup 1 SRAWI
351 "x" operand "n" operand "x" operand ADD
352 "x" operand dup 0 LWZ
354 { +input+ { { f "n" } } }
355 { +scratch+ { { f "x" } } }
357 { +clobber+ { "n" } }
361 "n" operand dup 1 SRAWI
363 "x" operand "n" operand "x" operand ADD
364 "val" operand "x" operand 0 STW
366 { +input+ { { f "val" } { f "n" } } }
367 { +scratch+ { { f "x" } } }
368 { +clobber+ { "n" } }