4 ;;;; Multiplication and Division helping routines.
6 ;;; ?? FIXME: Where are generic-* and generic-/?
8 (define-assembly-routine
10 ((:arg x (signed-reg) nl0-offset)
11 (:arg y (signed-reg) nl1-offset)
13 (:res res (signed-reg) nl2-offset)
15 (:temp tmp (unsigned-reg) nl3-offset)
16 (:temp sign (unsigned-reg) nl4-offset))
18 ;; Determine the sign of the result.
19 (inst extrs x 0 1 sign :=)
20 (inst sub zero-tn x x)
21 (inst extrs y 0 1 tmp :=)
22 (inst sub zero-tn y y)
23 (inst xor sign tmp sign)
25 ;; Make sure X is less then Y.
26 (inst comclr x y tmp :<<)
30 ;; Blow out of here if the result is zero.
31 (inst comb := x zero-tn done)
35 (inst extru x 31 1 zero-tn :ev)
37 (inst extru x 30 1 zero-tn :ev)
38 (inst sh1add y res res)
39 (inst extru x 29 1 zero-tn :ev)
40 (inst sh2add y res res)
41 (inst extru x 28 1 zero-tn :ev)
42 (inst sh3add y res res)
45 (inst comb :<> x zero-tn loop)
49 (inst xor res sign res)
50 (inst add res sign res))
52 (define-assembly-routine
54 ((:arg dividend signed-reg nl0-offset)
55 (:arg divisor signed-reg nl1-offset)
57 (:res quo signed-reg nl2-offset)
58 (:res rem signed-reg nl3-offset))
59 ;; Move abs(divident) into quo.
60 (inst move dividend quo :>=)
61 (inst sub zero-tn quo quo)
62 ;; Do one divive-step with -divisor to prime V (use rem as a temp)
63 (inst sub zero-tn divisor rem)
64 (inst ds zero-tn rem zero-tn)
65 ;; Shift the divident/quotient one bit, setting the carry flag.
66 (inst add quo quo quo)
67 ;; The first real divive-step.
68 (inst ds zero-tn divisor rem)
69 (inst addc quo quo quo)
70 ;; And 31 more of them.
72 (inst ds rem divisor rem)
73 (inst addc quo quo quo))
74 ;; If the remainder is negative, we need to add the absolute value of the
76 (inst comb :>= rem zero-tn remainder-positive)
77 (inst comclr divisor zero-tn zero-tn :<)
78 (inst add rem divisor rem :tr)
79 (inst sub rem divisor rem)
81 ;; Now we have to fix the signs of quo and rem.
82 (inst xor divisor dividend zero-tn :>=)
83 (inst sub zero-tn quo quo)
84 (inst move dividend zero-tn :>=)
85 (inst sub zero-tn rem rem))
88 ;;;; Generic arithmetic.
90 (define-assembly-routine (generic-+
92 (:return-style :full-call)
96 ((:arg x (descriptor-reg any-reg) a0-offset)
97 (:arg y (descriptor-reg any-reg) a1-offset)
98 (:res res (descriptor-reg any-reg) a0-offset)
99 (:temp temp non-descriptor-reg nl0-offset)
100 (:temp temp1 non-descriptor-reg nl1-offset)
101 (:temp temp2 non-descriptor-reg nl2-offset)
102 (:temp lra descriptor-reg lra-offset)
103 (:temp lip interior-reg lip-offset)
104 (:temp nargs any-reg nargs-offset)
105 (:temp ocfp any-reg ocfp-offset))
106 ;; If either arg is not fixnum, use two-arg-+ to summarize
108 (inst extru temp 31 3 zero-tn :=)
109 (inst b DO-STATIC-FUN :nullify t)
110 ;; check for overflow
112 (inst xor temp x temp1)
113 (inst xor temp y temp2)
114 (inst and temp1 temp2 temp1)
115 (inst bc :< nil temp1 zero-tn DO-OVERFLOW)
117 (lisp-return lra :offset 1)
120 ;; We did overflow, so do the bignum version
121 (inst sra x n-fixnum-tag-bits temp1)
122 (inst sra y n-fixnum-tag-bits temp2)
123 (inst add temp1 temp2 temp)
124 (with-fixed-allocation (res nil temp2 bignum-widetag
125 (1+ bignum-digits-offset) nil)
126 (storew temp res bignum-digits-offset other-pointer-lowtag))
127 (lisp-return lra :offset 1)
130 (inst ldw (static-fun-offset 'two-arg-+) null-tn lip)
131 (inst li (fixnumize 2) nargs)
134 (move csp-tn cfp-tn t))
136 (define-assembly-routine (generic--
138 (:return-style :full-call)
142 ((:arg x (descriptor-reg any-reg) a0-offset)
143 (:arg y (descriptor-reg any-reg) a1-offset)
145 (:res res (descriptor-reg any-reg) a0-offset)
147 (:temp temp non-descriptor-reg nl0-offset)
148 (:temp temp1 non-descriptor-reg nl1-offset)
149 (:temp temp2 non-descriptor-reg nl2-offset)
150 (:temp lra descriptor-reg lra-offset)
151 (:temp lip interior-reg lip-offset)
152 (:temp nargs any-reg nargs-offset)
153 (:temp ocfp any-reg ocfp-offset))
154 ;; If either arg is not fixnum, use two-arg-+ to summarize
156 (inst extru temp 31 3 zero-tn :=)
157 (inst b DO-STATIC-FUN :nullify t)
159 ;; check for overflow
161 (inst xor x temp temp2)
162 (inst and temp2 temp1 temp1)
163 (inst bc :< nil temp1 zero-tn DO-OVERFLOW)
165 (lisp-return lra :offset 1)
168 ;; We did overflow, so do the bignum version
169 (inst sra x n-fixnum-tag-bits temp1)
170 (inst sra y n-fixnum-tag-bits temp2)
171 (inst sub temp1 temp2 temp)
172 (with-fixed-allocation (res nil temp2 bignum-widetag
173 (1+ bignum-digits-offset) nil)
174 (storew temp res bignum-digits-offset other-pointer-lowtag))
175 (lisp-return lra :offset 1)
178 (inst ldw (static-fun-offset 'two-arg--) null-tn lip)
179 (inst li (fixnumize 2) nargs)
182 (move csp-tn cfp-tn t))
185 ;;;; Comparison routines.
188 ((define-cond-assem-rtn (name translate static-fn cond)
189 `(define-assembly-routine (,name
191 (:return-style :full-call)
193 (:translate ,translate)
195 ((:arg x (descriptor-reg any-reg) a0-offset)
196 (:arg y (descriptor-reg any-reg) a1-offset)
198 (:res res descriptor-reg a0-offset)
200 (:temp lip interior-reg lip-offset)
201 (:temp lra descriptor-reg lra-offset)
202 (:temp nargs any-reg nargs-offset)
203 (:temp ocfp any-reg ocfp-offset))
204 (inst extru x 31 2 zero-tn :=)
205 (inst b do-static-fn :nullify t)
206 (inst extru y 31 2 zero-tn :=)
207 (inst b do-static-fn :nullify t)
209 (inst comclr x y zero-tn ,cond)
210 (inst move null-tn res :tr)
212 (lisp-return lra :offset 1)
215 (inst ldw (static-fun-offset ',static-fn) null-tn lip)
216 (inst li (fixnumize 2) nargs)
217 (inst move cfp-tn ocfp)
219 (inst move csp-tn cfp-tn))))
221 (define-cond-assem-rtn generic-< < two-arg-< :<)
222 (define-cond-assem-rtn generic-> > two-arg-> :>))
225 (define-assembly-routine
228 (:return-style :full-call)
232 ((:arg x (descriptor-reg any-reg) a0-offset)
233 (:arg y (descriptor-reg any-reg) a1-offset)
235 (:res res descriptor-reg a0-offset)
237 (:temp lip interior-reg lip-offset)
238 (:temp lra descriptor-reg lra-offset)
239 (:temp nargs any-reg nargs-offset)
240 (:temp ocfp any-reg ocfp-offset))
242 (inst comb := x y return-t :nullify t)
243 (inst extru x 31 2 zero-tn :<>)
244 (inst b return-nil :nullify t)
245 (inst extru y 31 2 zero-tn :=)
246 (inst b do-static-fn :nullify t)
249 (inst move null-tn res)
250 (lisp-return lra :offset 1)
253 (inst ldw (static-fun-offset 'eql) null-tn lip)
254 (inst li (fixnumize 2) nargs)
255 (inst move cfp-tn ocfp)
257 (inst move csp-tn cfp-tn)
262 (define-assembly-routine
265 (:return-style :full-call)
269 ((:arg x (descriptor-reg any-reg) a0-offset)
270 (:arg y (descriptor-reg any-reg) a1-offset)
272 (:res res descriptor-reg a0-offset)
274 (:temp lip interior-reg lip-offset)
275 (:temp lra descriptor-reg lra-offset)
276 (:temp nargs any-reg nargs-offset)
277 (:temp ocfp any-reg ocfp-offset))
279 (inst comb := x y return-t :nullify t)
280 (inst extru x 31 2 zero-tn :=)
281 (inst b do-static-fn :nullify t)
282 (inst extru y 31 2 zero-tn :=)
283 (inst b do-static-fn :nullify t)
285 (inst move null-tn res)
286 (lisp-return lra :offset 1)
289 (inst ldw (static-fun-offset 'two-arg-=) null-tn lip)
290 (inst li (fixnumize 2) nargs)
291 (inst move cfp-tn ocfp)
293 (inst move csp-tn cfp-tn)