lib1funcs.S 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /* libgcc routines for the MCore.
  2. Copyright (C) 1993-2022 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 3, or (at your option) any
  7. later version.
  8. This file is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. #define CONCAT1(a, b) CONCAT2(a, b)
  20. #define CONCAT2(a, b) a ## b
  21. /* Use the right prefix for global labels. */
  22. #define SYM(x) CONCAT1 (__, x)
  23. #ifdef __ELF__
  24. #define TYPE(x) .type SYM (x),@function
  25. #define SIZE(x) .size SYM (x), . - SYM (x)
  26. #else
  27. #define TYPE(x)
  28. #define SIZE(x)
  29. #endif
  30. .macro FUNC_START name
  31. .text
  32. .globl SYM (\name)
  33. TYPE (\name)
  34. SYM (\name):
  35. .endm
  36. .macro FUNC_END name
  37. SIZE (\name)
  38. .endm
  39. #ifdef L_udivsi3
  40. FUNC_START udiv32
  41. FUNC_START udivsi32
  42. movi r1,0 // r1-r2 form 64 bit dividend
  43. movi r4,1 // r4 is quotient (1 for a sentinel)
  44. cmpnei r3,0 // look for 0 divisor
  45. bt 9f
  46. trap 3 // divide by 0
  47. 9:
  48. // control iterations; skip across high order 0 bits in dividend
  49. mov r7,r2
  50. cmpnei r7,0
  51. bt 8f
  52. movi r2,0 // 0 dividend
  53. jmp r15 // quick return
  54. 8:
  55. ff1 r7 // figure distance to skip
  56. lsl r4,r7 // move the sentinel along (with 0's behind)
  57. lsl r2,r7 // and the low 32 bits of numerator
  58. // appears to be wrong...
  59. // tested out incorrectly in our OS work...
  60. // mov r7,r3 // looking at divisor
  61. // ff1 r7 // I can move 32-r7 more bits to left.
  62. // addi r7,1 // ok, one short of that...
  63. // mov r1,r2
  64. // lsr r1,r7 // bits that came from low order...
  65. // rsubi r7,31 // r7 == "32-n" == LEFT distance
  66. // addi r7,1 // this is (32-n)
  67. // lsl r4,r7 // fixes the high 32 (quotient)
  68. // lsl r2,r7
  69. // cmpnei r4,0
  70. // bf 4f // the sentinel went away...
  71. // run the remaining bits
  72. 1: lslc r2,1 // 1 bit left shift of r1-r2
  73. addc r1,r1
  74. cmphs r1,r3 // upper 32 of dividend >= divisor?
  75. bf 2f
  76. sub r1,r3 // if yes, subtract divisor
  77. 2: addc r4,r4 // shift by 1 and count subtracts
  78. bf 1b // if sentinel falls out of quotient, stop
  79. 4: mov r2,r4 // return quotient
  80. mov r3,r1 // and piggyback the remainder
  81. jmp r15
  82. FUNC_END udiv32
  83. FUNC_END udivsi32
  84. #endif
  85. #ifdef L_umodsi3
  86. FUNC_START urem32
  87. FUNC_START umodsi3
  88. movi r1,0 // r1-r2 form 64 bit dividend
  89. movi r4,1 // r4 is quotient (1 for a sentinel)
  90. cmpnei r3,0 // look for 0 divisor
  91. bt 9f
  92. trap 3 // divide by 0
  93. 9:
  94. // control iterations; skip across high order 0 bits in dividend
  95. mov r7,r2
  96. cmpnei r7,0
  97. bt 8f
  98. movi r2,0 // 0 dividend
  99. jmp r15 // quick return
  100. 8:
  101. ff1 r7 // figure distance to skip
  102. lsl r4,r7 // move the sentinel along (with 0's behind)
  103. lsl r2,r7 // and the low 32 bits of numerator
  104. 1: lslc r2,1 // 1 bit left shift of r1-r2
  105. addc r1,r1
  106. cmphs r1,r3 // upper 32 of dividend >= divisor?
  107. bf 2f
  108. sub r1,r3 // if yes, subtract divisor
  109. 2: addc r4,r4 // shift by 1 and count subtracts
  110. bf 1b // if sentinel falls out of quotient, stop
  111. mov r2,r1 // return remainder
  112. jmp r15
  113. FUNC_END urem32
  114. FUNC_END umodsi3
  115. #endif
  116. #ifdef L_divsi3
  117. FUNC_START div32
  118. FUNC_START divsi3
  119. mov r5,r2 // calc sign of quotient
  120. xor r5,r3
  121. abs r2 // do unsigned divide
  122. abs r3
  123. movi r1,0 // r1-r2 form 64 bit dividend
  124. movi r4,1 // r4 is quotient (1 for a sentinel)
  125. cmpnei r3,0 // look for 0 divisor
  126. bt 9f
  127. trap 3 // divide by 0
  128. 9:
  129. // control iterations; skip across high order 0 bits in dividend
  130. mov r7,r2
  131. cmpnei r7,0
  132. bt 8f
  133. movi r2,0 // 0 dividend
  134. jmp r15 // quick return
  135. 8:
  136. ff1 r7 // figure distance to skip
  137. lsl r4,r7 // move the sentinel along (with 0's behind)
  138. lsl r2,r7 // and the low 32 bits of numerator
  139. // tested out incorrectly in our OS work...
  140. // mov r7,r3 // looking at divisor
  141. // ff1 r7 // I can move 32-r7 more bits to left.
  142. // addi r7,1 // ok, one short of that...
  143. // mov r1,r2
  144. // lsr r1,r7 // bits that came from low order...
  145. // rsubi r7,31 // r7 == "32-n" == LEFT distance
  146. // addi r7,1 // this is (32-n)
  147. // lsl r4,r7 // fixes the high 32 (quotient)
  148. // lsl r2,r7
  149. // cmpnei r4,0
  150. // bf 4f // the sentinel went away...
  151. // run the remaining bits
  152. 1: lslc r2,1 // 1 bit left shift of r1-r2
  153. addc r1,r1
  154. cmphs r1,r3 // upper 32 of dividend >= divisor?
  155. bf 2f
  156. sub r1,r3 // if yes, subtract divisor
  157. 2: addc r4,r4 // shift by 1 and count subtracts
  158. bf 1b // if sentinel falls out of quotient, stop
  159. 4: mov r2,r4 // return quotient
  160. mov r3,r1 // piggyback the remainder
  161. btsti r5,31 // after adjusting for sign
  162. bf 3f
  163. rsubi r2,0
  164. rsubi r3,0
  165. 3: jmp r15
  166. FUNC_END div32
  167. FUNC_END divsi3
  168. #endif
  169. #ifdef L_modsi3
  170. FUNC_START rem32
  171. FUNC_START modsi3
  172. mov r5,r2 // calc sign of remainder
  173. abs r2 // do unsigned divide
  174. abs r3
  175. movi r1,0 // r1-r2 form 64 bit dividend
  176. movi r4,1 // r4 is quotient (1 for a sentinel)
  177. cmpnei r3,0 // look for 0 divisor
  178. bt 9f
  179. trap 3 // divide by 0
  180. 9:
  181. // control iterations; skip across high order 0 bits in dividend
  182. mov r7,r2
  183. cmpnei r7,0
  184. bt 8f
  185. movi r2,0 // 0 dividend
  186. jmp r15 // quick return
  187. 8:
  188. ff1 r7 // figure distance to skip
  189. lsl r4,r7 // move the sentinel along (with 0's behind)
  190. lsl r2,r7 // and the low 32 bits of numerator
  191. 1: lslc r2,1 // 1 bit left shift of r1-r2
  192. addc r1,r1
  193. cmphs r1,r3 // upper 32 of dividend >= divisor?
  194. bf 2f
  195. sub r1,r3 // if yes, subtract divisor
  196. 2: addc r4,r4 // shift by 1 and count subtracts
  197. bf 1b // if sentinel falls out of quotient, stop
  198. mov r2,r1 // return remainder
  199. btsti r5,31 // after adjusting for sign
  200. bf 3f
  201. rsubi r2,0
  202. 3: jmp r15
  203. FUNC_END rem32
  204. FUNC_END modsi3
  205. #endif
  206. /* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2}
  207. will behave as __cmpdf2. So, we stub the implementations to
  208. jump on to __cmpdf2 and __cmpsf2.
  209. All of these shortcircuit the return path so that __cmp{sd}f2
  210. will go directly back to the caller. */
  211. .macro COMPARE_DF_JUMP name
  212. .import SYM (cmpdf2)
  213. FUNC_START \name
  214. jmpi SYM (cmpdf2)
  215. FUNC_END \name
  216. .endm
  217. #ifdef L_eqdf2
  218. COMPARE_DF_JUMP eqdf2
  219. #endif /* L_eqdf2 */
  220. #ifdef L_nedf2
  221. COMPARE_DF_JUMP nedf2
  222. #endif /* L_nedf2 */
  223. #ifdef L_gtdf2
  224. COMPARE_DF_JUMP gtdf2
  225. #endif /* L_gtdf2 */
  226. #ifdef L_gedf2
  227. COMPARE_DF_JUMP gedf2
  228. #endif /* L_gedf2 */
  229. #ifdef L_ltdf2
  230. COMPARE_DF_JUMP ltdf2
  231. #endif /* L_ltdf2 */
  232. #ifdef L_ledf2
  233. COMPARE_DF_JUMP ledf2
  234. #endif /* L_ledf2 */
  235. /* SINGLE PRECISION FLOATING POINT STUBS */
  236. .macro COMPARE_SF_JUMP name
  237. .import SYM (cmpsf2)
  238. FUNC_START \name
  239. jmpi SYM (cmpsf2)
  240. FUNC_END \name
  241. .endm
  242. #ifdef L_eqsf2
  243. COMPARE_SF_JUMP eqsf2
  244. #endif /* L_eqsf2 */
  245. #ifdef L_nesf2
  246. COMPARE_SF_JUMP nesf2
  247. #endif /* L_nesf2 */
  248. #ifdef L_gtsf2
  249. COMPARE_SF_JUMP gtsf2
  250. #endif /* L_gtsf2 */
  251. #ifdef L_gesf2
  252. COMPARE_SF_JUMP __gesf2
  253. #endif /* L_gesf2 */
  254. #ifdef L_ltsf2
  255. COMPARE_SF_JUMP __ltsf2
  256. #endif /* L_ltsf2 */
  257. #ifdef L_lesf2
  258. COMPARE_SF_JUMP lesf2
  259. #endif /* L_lesf2 */