1 /* Assembly functions for the Xtensa version of libgcc1.
2 Copyright
(C
) 2001,2002,2003 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"
33 # Define macros for the ABS
and ADDX
* instructions to handle cases
34 # where they are
not included
in the Xtensa processor configuration.
36 .
macro do_abs dst
, src
, tmp
41 movgez
\tmp
, \src
, \src
46 .
macro do_addx2 dst
, as
, at
, tmp
55 .
macro do_addx4 dst
, as
, at
, tmp
64 .
macro do_addx8 dst
, as
, at
, tmp
76 .
type __mulsi3
,@function
96 #elif XCHAL_HAVE_MAC16
105 #else
/* !XCHAL_HAVE_MUL16
&& !XCHAL_HAVE_MAC16
*/
107 # Multiply one bit at a time
, but unroll the
loop 4x to better
108 # exploit the addx instructions
and avoid overhead.
109 # Peel the first iteration to save a cycle on init.
111 # Avoid negative numbers.
112 xor a5
, a2
, a3 # top bit is
1 iff one of the inputs is negative
116 # Swap so the second argument is smaller.
119 movgez a4
, a2
, a7 # a4
= max
(a2
, a3
)
120 movltz a3
, a2
, a7 # a3
= min
(a2
, a3
)
126 do_addx2 a7
, a4
, a2
, a7
130 do_addx4 a7
, a4
, a2
, a7
134 do_addx8 a7
, a4
, a2
, a7
138 bgeui a3
, 16, .Lmult_main_loop
152 do_addx2 a7
, a4
, a2
, a7
156 do_addx4 a7
, a4
, a2
, a7
160 do_addx8 a7
, a4
, a2
, a7
164 bgeui a3
, 16, .Lmult_main_loop
169 #endif
/* !XCHAL_HAVE_MUL16
&& !XCHAL_HAVE_MAC16
*/
172 .
size __mulsi3
,.
-__mulsi3
174 #endif
/* L_mulsi3
*/
177 # Define a
macro for the NSAU
(unsigned normalize shift amount
)
178 # instruction
, which computes the number of leading zero bits
,
179 # to handle cases where it is
not included
in the Xtensa processor
182 .
macro do_nsau cnt
, val
, tmp
, a
188 extui
\tmp
, \a, 16, 16
193 extui
\tmp
, \a, 24, 8
198 movi
\tmp
, __nsau_data
203 #endif
/* !XCHAL_HAVE_NSA
*/
210 .
type __nsau_data
,@object
213 .
byte 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4
214 .
byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
215 .
byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
216 .
byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
217 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
218 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
219 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
220 .
byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
221 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
222 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
223 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
224 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
225 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
226 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
227 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
228 .
byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
229 #endif
/* !XCHAL_HAVE_NSA
*/
230 .
size __nsau_data
,.
-__nsau_data
238 .
type __udivsi3
,@function
241 bltui a3
, 2, .Lle_one # check if the divisor
<= 1
243 mov a6
, a2 # keep dividend
in a6
244 do_nsau a5
, a6
, a2
, a7 # dividend_shift
= nsau
(dividend
)
245 do_nsau a4
, a3
, a2
, a7 # divisor_shift
= nsau
(divisor
)
246 bgeu a5
, a4
, .Lspecial
248 sub a4
, a4
, a5 # count
= divisor_shift
- dividend_shift
250 sll a3
, a3 # divisor
<<= count
251 movi a2
, 0 # quotient
= 0
253 #
test-subtract
-and-shift
loop; one quotient bit on each iteration
255 loopnez a4
, .Lloopend
256 #endif
/* XCHAL_HAVE_LOOPS
*/
258 bltu a6
, a3
, .Lzerobit
264 #if
!XCHAL_HAVE_LOOPS
267 #endif
/* !XCHAL_HAVE_LOOPS
*/
270 bltu a6
, a3
, .Lreturn
271 addi a2
, a2
, 1 # increment quotient if dividend
>= divisor
276 # return dividend
>= divisor
278 bltu a6
, a3
, .Lreturn2
284 beqz a3
, .Lerror # if divisor
== 1, return the dividend
287 movi a2
, 0 # just return
0; could throw an exception
289 .
size __udivsi3
,.
-__udivsi3
291 #endif
/* L_udivsi3
*/
297 .
type __divsi3
,@function
300 xor a7
, a2
, a3 # sign
= dividend ^ divisor
301 do_abs a6
, a2
, a4 # udividend
= abs
(dividend
)
302 do_abs a3
, a3
, a4 # udivisor
= abs
(divisor
)
303 bltui a3
, 2, .Lle_one # check if udivisor
<= 1
304 do_nsau a5
, a6
, a2
, a8 # udividend_shift
= nsau
(udividend
)
305 do_nsau a4
, a3
, a2
, a8 # udivisor_shift
= nsau
(udivisor
)
306 bgeu a5
, a4
, .Lspecial
308 sub a4
, a4
, a5 # count
= udivisor_shift
- udividend_shift
310 sll a3
, a3 # udivisor
<<= count
311 movi a2
, 0 # quotient
= 0
313 #
test-subtract
-and-shift
loop; one quotient bit on each iteration
315 loopnez a4
, .Lloopend
316 #endif
/* XCHAL_HAVE_LOOPS
*/
318 bltu a6
, a3
, .Lzerobit
324 #if
!XCHAL_HAVE_LOOPS
327 #endif
/* !XCHAL_HAVE_LOOPS
*/
330 bltu a6
, a3
, .Lreturn
331 addi a2
, a2
, 1 # increment quotient if udividend
>= udivisor
334 movltz a2
, a5
, a7 # return
(sign
< 0) ? -quotient
: quotient
339 bltu a6
, a3
, .Lreturn2 # if dividend
< divisor
, return
0
342 movltz a2
, a4
, a7 # else return
(sign
< 0) ? -1 : 1
348 neg a2
, a6 # if udivisor
== 1, then return...
349 movgez a2
, a6
, a7 #
(sign
< 0) ? -udividend
: udividend
352 movi a2
, 0 # just return
0; could throw an exception
354 .
size __divsi3
,.
-__divsi3
356 #endif
/* L_divsi3
*/
362 .
type __umodsi3
,@function
365 bltui a3
, 2, .Lle_one # check if the divisor is
<= 1
367 do_nsau a5
, a2
, a6
, a7 # dividend_shift
= nsau
(dividend
)
368 do_nsau a4
, a3
, a6
, a7 # divisor_shift
= nsau
(divisor
)
369 bgeu a5
, a4
, .Lspecial
371 sub a4
, a4
, a5 # count
= divisor_shift
- dividend_shift
373 sll a3
, a3 # divisor
<<= count
375 #
test-subtract
-and-shift
loop
377 loopnez a4
, .Lloopend
378 #endif
/* XCHAL_HAVE_LOOPS
*/
380 bltu a2
, a3
, .Lzerobit
384 #if
!XCHAL_HAVE_LOOPS
387 #endif
/* !XCHAL_HAVE_LOOPS
*/
390 bltu a2
, a3
, .Lreturn
391 sub a2
, a2
, a3 # subtract once more if dividend
>= divisor
396 bltu a2
, a3
, .Lreturn2
397 sub a2
, a2
, a3 # subtract once if dividend
>= divisor
402 # the divisor is either
0 or 1, so just return
0.
403 # someday we may want to throw an exception if the divisor is
0.
406 .
size __umodsi3
,.
-__umodsi3
408 #endif
/* L_umodsi3
*/
414 .
type __modsi3
,@function
417 mov a7
, a2 # save original
(signed
) dividend
418 do_abs a2
, a2
, a4 # udividend
= abs
(dividend
)
419 do_abs a3
, a3
, a4 # udivisor
= abs
(divisor
)
420 bltui a3
, 2, .Lle_one # check if udivisor
<= 1
421 do_nsau a5
, a2
, a6
, a8 # udividend_shift
= nsau
(udividend
)
422 do_nsau a4
, a3
, a6
, a8 # udivisor_shift
= nsau
(udivisor
)
423 bgeu a5
, a4
, .Lspecial
425 sub a4
, a4
, a5 # count
= udivisor_shift
- udividend_shift
427 sll a3
, a3 # udivisor
<<= count
429 #
test-subtract
-and-shift
loop
431 loopnez a4
, .Lloopend
432 #endif
/* XCHAL_HAVE_LOOPS
*/
434 bltu a2
, a3
, .Lzerobit
438 #if
!XCHAL_HAVE_LOOPS
441 #endif
/* !XCHAL_HAVE_LOOPS
*/
444 bltu a2
, a3
, .Lreturn
445 sub a2
, a2
, a3 # subtract once more if udividend
>= udivisor
448 neg a2
, a2 # if
(dividend
< 0), return
-udividend
453 bltu a2
, a3
, .Lreturn2
454 sub a2
, a2
, a3 # subtract once if dividend
>= divisor
457 neg a2
, a2 # if
(dividend
< 0), return
-udividend
462 # udivisor is either
0 or 1, so just return
0.
463 # someday we may want to throw an exception if udivisor is
0.
466 .
size __modsi3
,.
-__modsi3
468 #endif
/* L_modsi3
*/