1 /* Assembly functions for the Xtensa version of libgcc1.
2 Copyright
(C
) 2001,2002 Free Software Foundation
, Inc.
3 Contributed by Bob Wilson
(bwilson
@tensilica.com
) at Tensilica.
5 This file is part of GCC.
7 GCC is free software
; you can redistribute it and/or modify it under
8 the terms of the GNU General
Public License as published by the Free
9 Software Foundation
; either version 2, or (at your option) any later
12 In addition to the permissions
in the GNU General
Public License
, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of
this file
into combinations with other programs
,
15 and to distribute those combinations without any restriction coming
16 from the use of
this file.
(The General
Public License restrictions
17 do apply
in other respects
; for example, they cover modification of
18 the file
, and distribution when
not linked
into a combine
21 GCC is distributed
in the hope that it will be useful
, but WITHOUT ANY
22 WARRANTY
; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License
26 You should have received a copy of the GNU General
Public License
27 along with GCC
; see the file COPYING. If not, write to the Free
28 Software Foundation
, 59 Temple Place
- Suite
330, Boston
, MA
31 #
include "xtensa/xtensa-config.h"
36 .
type __mulsi3
,@function
56 #elif XCHAL_HAVE_MAC16
65 #else
/* !XCHAL_HAVE_MUL16
&& !XCHAL_HAVE_MAC16
*/
67 # Multiply one bit at a time
, but unroll the
loop 4x to better
68 # exploit the addx instructions.
70 # Peel the first iteration to save a cycle on init
72 # avoid negative numbers
74 xor a5
, a2
, a3 # top bit is
1 iff one of the inputs is negative
78 # swap so that second argument is smaller
81 movgez a4
, a2
, a7 # a4
= max
(a2
, a3
)
82 movltz a3
, a2
, a7 # a3
= min
(a2
, a3
)
100 bgeui a3
, 16, .Lmult_main_loop
128 bgeui a3
, 16, .Lmult_main_loop
133 #endif
/* !XCHAL_HAVE_MUL16
&& !XCHAL_HAVE_MAC16
*/
137 .
size __mulsi3
,.Lfe0
-__mulsi3
139 #endif
/* L_mulsi3
*/
142 # Some Xtensa configurations
include the NSAU
(unsigned
143 # normalize shift amount
) instruction which computes the number
144 # of leading zero bits. For other configurations
, the
"nsau"
145 # operation is implemented as a
macro.
148 .
macro nsau cnt
, val
, tmp
, a
151 extui
\tmp
, \a, 16, 16
156 extui
\tmp
, \a, 24, 8
161 movi
\tmp
, __nsau_data
167 #endif
/* !XCHAL_HAVE_NSA
*/
173 .
type __nsau_data
,@object
176 .
byte 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4
177 .
byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
178 .
byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
179 .
byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
180 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
181 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
182 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
183 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
184 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
185 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
186 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
187 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
188 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
189 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
190 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
191 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
192 #endif
/* !XCHAL_HAVE_NSA
*/
194 .
size __nsau_data
,.Lfe1
-__nsau_data
202 .
type __udivsi3
,@function
205 bltui a3
, 2, .Lle_one # check if the divisor
<= 1
207 mov a6
, a2 # keep dividend
in a6
209 nsau a5
, a6 # dividend_shift
= nsau
(dividend
)
210 nsau a4
, a3 # divisor_shift
= nsau
(divisor
)
211 #else
/* !XCHAL_HAVE_NSA
*/
212 nsau a5
, a6
, a2
, a7 # dividend_shift
= nsau
(dividend
)
213 nsau a4
, a3
, a2
, a7 # divisor_shift
= nsau
(divisor
)
214 #endif
/* !XCHAL_HAVE_NSA
*/
215 bgeu a5
, a4
, .Lspecial
217 sub a4
, a4
, a5 # count
= divisor_shift
- dividend_shift
219 sll a3
, a3 # divisor
<<= count
220 movi a2
, 0 # quotient
= 0
222 #
test-subtract
-and-shift
loop; one quotient bit on each iteration
224 loopnez a4
, .Lloopend
225 #endif
/* XCHAL_HAVE_LOOPS
*/
227 bltu a6
, a3
, .Lzerobit
233 #if
!XCHAL_HAVE_LOOPS
236 #endif
/* !XCHAL_HAVE_LOOPS
*/
239 bltu a6
, a3
, .Lreturn
240 addi a2
, a2
, 1 # increment quotient if dividend
>= divisor
245 # return dividend
>= divisor
247 bltu a6
, a3
, .Lreturn2
253 beqz a3
, .Lerror # if divisor
== 1, return the dividend
256 movi a2
, 0 # just return
0; could throw an exception
259 .
size __udivsi3
,.Lfe2
-__udivsi3
261 #endif
/* L_udivsi3
*/
267 .
type __divsi3
,@function
270 xor a7
, a2
, a3 # sign
= dividend ^ divisor
271 abs a6
, a2 # udividend
= abs
(dividend
)
272 abs a3
, a3 # udivisor
= abs
(divisor
)
273 bltui a3
, 2, .Lle_one # check if udivisor
<= 1
275 nsau a5
, a6 # udividend_shift
= nsau
(udividend
)
276 nsau a4
, a3 # udivisor_shift
= nsau
(udivisor
)
277 #else
/* !XCHAL_HAVE_NSA
*/
278 nsau a5
, a6
, a2
, a8 # udividend_shift
= nsau
(udividend
)
279 nsau a4
, a3
, a2
, a8 # udivisor_shift
= nsau
(udivisor
)
280 #endif
/* !XCHAL_HAVE_NSA
*/
281 bgeu a5
, a4
, .Lspecial
283 sub a4
, a4
, a5 # count
= udivisor_shift
- udividend_shift
285 sll a3
, a3 # udivisor
<<= count
286 movi a2
, 0 # quotient
= 0
288 #
test-subtract
-and-shift
loop; one quotient bit on each iteration
290 loopnez a4
, .Lloopend
291 #endif
/* XCHAL_HAVE_LOOPS
*/
293 bltu a6
, a3
, .Lzerobit
299 #if
!XCHAL_HAVE_LOOPS
302 #endif
/* !XCHAL_HAVE_LOOPS
*/
305 bltu a6
, a3
, .Lreturn
306 addi a2
, a2
, 1 # increment quotient if udividend
>= udivisor
309 movltz a2
, a5
, a7 # return
(sign
< 0) ? -quotient
: quotient
314 bltu a6
, a3
, .Lreturn2 # if dividend
< divisor
, return
0
317 movltz a2
, a4
, a7 # else return
(sign
< 0) ? -1 : 1
323 neg a2
, a6 # if udivisor
== 1, then return...
324 movgez a2
, a6
, a7 #
(sign
< 0) ? -udividend
: udividend
327 movi a2
, 0 # just return
0; could throw an exception
330 .
size __divsi3
,.Lfe3
-__divsi3
332 #endif
/* L_divsi3
*/
338 .
type __umodsi3
,@function
341 bltui a3
, 2, .Lle_one # check if the divisor is
<= 1
344 nsau a5
, a2 # dividend_shift
= nsau
(dividend
)
345 nsau a4
, a3 # divisor_shift
= nsau
(divisor
)
346 #else
/* !XCHAL_HAVE_NSA
*/
347 nsau a5
, a2
, a6
, a7 # dividend_shift
= nsau
(dividend
)
348 nsau a4
, a3
, a6
, a7 # divisor_shift
= nsau
(divisor
)
349 #endif
/* !XCHAL_HAVE_NSA
*/
350 bgeu a5
, a4
, .Lspecial
352 sub a4
, a4
, a5 # count
= divisor_shift
- dividend_shift
354 sll a3
, a3 # divisor
<<= count
356 #
test-subtract
-and-shift
loop
358 loopnez a4
, .Lloopend
359 #endif
/* XCHAL_HAVE_LOOPS
*/
361 bltu a2
, a3
, .Lzerobit
365 #if
!XCHAL_HAVE_LOOPS
368 #endif
/* !XCHAL_HAVE_LOOPS
*/
371 bltu a2
, a3
, .Lreturn
372 sub a2
, a2
, a3 # subtract once more if dividend
>= divisor
377 bltu a2
, a3
, .Lreturn2
378 sub a2
, a2
, a3 # subtract once if dividend
>= divisor
383 # the divisor is either
0 or 1, so just return
0.
384 # someday we may want to throw an exception if the divisor is
0.
388 .
size __umodsi3
,.Lfe4
-__umodsi3
390 #endif
/* L_umodsi3
*/
396 .
type __modsi3
,@function
399 mov a7
, a2 # save original
(signed
) dividend
400 abs a2
, a2 # udividend
= abs
(dividend
)
401 abs a3
, a3 # udivisor
= abs
(divisor
)
402 bltui a3
, 2, .Lle_one # check if udivisor
<= 1
404 nsau a5
, a2 # udividend_shift
= nsau
(udividend
)
405 nsau a4
, a3 # udivisor_shift
= nsau
(udivisor
)
406 #else
/* !XCHAL_HAVE_NSA
*/
407 nsau a5
, a2
, a6
, a8 # udividend_shift
= nsau
(udividend
)
408 nsau a4
, a3
, a6
, a8 # udivisor_shift
= nsau
(udivisor
)
409 #endif
/* !XCHAL_HAVE_NSA
*/
410 bgeu a5
, a4
, .Lspecial
412 sub a4
, a4
, a5 # count
= udivisor_shift
- udividend_shift
414 sll a3
, a3 # udivisor
<<= count
416 #
test-subtract
-and-shift
loop
418 loopnez a4
, .Lloopend
419 #endif
/* XCHAL_HAVE_LOOPS
*/
421 bltu a2
, a3
, .Lzerobit
425 #if
!XCHAL_HAVE_LOOPS
428 #endif
/* !XCHAL_HAVE_LOOPS
*/
431 bltu a2
, a3
, .Lreturn
432 sub a2
, a2
, a3 # subtract once more if udividend
>= udivisor
435 neg a2
, a2 # if
(dividend
< 0), return
-udividend
440 bltu a2
, a3
, .Lreturn2
441 sub a2
, a2
, a3 # subtract once if dividend
>= divisor
444 neg a2
, a2 # if
(dividend
< 0), return
-udividend
449 # udivisor is either
0 or 1, so just return
0.
450 # someday we may want to throw an exception if udivisor is
0.
454 .
size __modsi3
,.Lfe5
-__modsi3
456 #endif
/* L_modsi3
*/