divmodqi.S 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* QImode div/mod functions for the GCC support library for the Renesas RL78 processors.
  2. Copyright (C) 2012-2022 Free Software Foundation, Inc.
  3. Contributed by Red Hat.
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. GCC is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. #include "vregs.h"
  21. .macro MAKE_GENERIC which,need_result
  22. .if \need_result
  23. quot = r8
  24. num = r10
  25. den = r12
  26. bit = r14
  27. .else
  28. num = r8
  29. quot = r10
  30. den = r12
  31. bit = r14
  32. .endif
  33. #define bit b
  34. #define den c
  35. #define bitden bc
  36. START_FUNC __generic_qidivmod\which
  37. num_lt_den\which:
  38. .if \need_result
  39. mov r8, #0
  40. .else
  41. mov a, [hl+4]
  42. mov r8, a
  43. .endif
  44. ret
  45. num_eq_den\which:
  46. .if \need_result
  47. mov r8, #1
  48. .else
  49. mov r8, #0
  50. .endif
  51. ret
  52. den_is_zero\which:
  53. mov r8, #0x00
  54. ret
  55. ;; These routines leave DE alone - the signed functions use DE
  56. ;; to store sign information that must remain intact
  57. .if \need_result
  58. .global __generic_qidiv
  59. __generic_qidiv:
  60. .else
  61. .global __generic_qimod
  62. __generic_qimod:
  63. .endif
  64. ;; (quot,rem) = 4[hl] /% 6[hl]
  65. mov a, [hl+4] ; num
  66. cmp a, [hl+6] ; den
  67. bz $num_eq_den\which
  68. bnh $num_lt_den\which
  69. ;; copy numerator
  70. ; mov a, [hl+4] ; already there from above
  71. mov num, a
  72. ;; copy denomonator
  73. mov a, [hl+6]
  74. mov den, a
  75. cmp0 den
  76. bz $den_is_zero\which
  77. den_not_zero\which:
  78. .if \need_result
  79. ;; zero out quot
  80. mov quot, #0
  81. .endif
  82. ;; initialize bit to 1
  83. mov bit, #1
  84. ; while (den < num && !(den & (1L << BITS_MINUS_1)))
  85. shift_den_bit\which:
  86. .macro SDB_ONE\which
  87. mov a, den
  88. mov1 cy,a.7
  89. bc $enter_main_loop\which
  90. cmp a, num
  91. bh $enter_main_loop\which
  92. ;; den <<= 1
  93. ; mov a, den ; already has it from the cmpw above
  94. shl a, 1
  95. mov den, a
  96. ;; bit <<= 1
  97. shl bit, 1
  98. .endm
  99. SDB_ONE\which
  100. SDB_ONE\which
  101. br $shift_den_bit\which
  102. main_loop\which:
  103. ;; if (num >= den) (cmp den > num)
  104. mov a, den
  105. cmp a, num
  106. bh $next_loop\which
  107. ;; num -= den
  108. mov a, num
  109. sub a, den
  110. mov num, a
  111. .if \need_result
  112. ;; res |= bit
  113. mov a, quot
  114. or a, bit
  115. mov quot, a
  116. .endif
  117. next_loop\which:
  118. ;; den, bit >>= 1
  119. movw ax, bitden
  120. shrw ax, 1
  121. movw bitden, ax
  122. enter_main_loop\which:
  123. cmp0 bit
  124. bnz $main_loop\which
  125. main_loop_done\which:
  126. ret
  127. END_FUNC __generic_qidivmod\which
  128. .endm
  129. ;----------------------------------------------------------------------
  130. MAKE_GENERIC _d 1
  131. MAKE_GENERIC _m 0
  132. ;----------------------------------------------------------------------
  133. START_FUNC ___udivqi3
  134. ;; r8 = 4[sp] / 6[sp]
  135. movw hl, sp
  136. br $!__generic_qidiv
  137. END_FUNC ___udivqi3
  138. START_FUNC ___umodqi3
  139. ;; r8 = 4[sp] % 6[sp]
  140. movw hl, sp
  141. br $!__generic_qimod
  142. END_FUNC ___umodqi3
  143. ;----------------------------------------------------------------------
  144. .macro NEG_AX
  145. movw hl, ax
  146. mov a, #0
  147. sub a, [hl]
  148. mov [hl], a
  149. .endm
  150. ;----------------------------------------------------------------------
  151. START_FUNC ___divqi3
  152. ;; r8 = 4[sp] / 6[sp]
  153. movw hl, sp
  154. movw de, #0
  155. mov a, [sp+4]
  156. mov1 cy, a.7
  157. bc $div_signed_num
  158. mov a, [sp+6]
  159. mov1 cy, a.7
  160. bc $div_signed_den
  161. br $!__generic_qidiv
  162. div_signed_num:
  163. ;; neg [sp+4]
  164. mov a, #0
  165. sub a, [hl+4]
  166. mov [hl+4], a
  167. mov d, #1
  168. mov a, [sp+6]
  169. mov1 cy, a.6
  170. bnc $div_unsigned_den
  171. div_signed_den:
  172. ;; neg [sp+6]
  173. mov a, #0
  174. sub a, [hl+6]
  175. mov [hl+6], a
  176. mov e, #1
  177. div_unsigned_den:
  178. call $!__generic_qidiv
  179. mov a, d
  180. cmp0 a
  181. bz $div_skip_restore_num
  182. ;; We have to restore the numerator [sp+4]
  183. movw ax, sp
  184. addw ax, #4
  185. NEG_AX
  186. mov a, d
  187. div_skip_restore_num:
  188. xor a, e
  189. bz $div_no_neg
  190. movw ax, #r8
  191. NEG_AX
  192. div_no_neg:
  193. mov a, e
  194. cmp0 a
  195. bz $div_skip_restore_den
  196. movw ax, sp
  197. addw ax, #6
  198. NEG_AX
  199. div_skip_restore_den:
  200. ret
  201. END_FUNC ___divqi3
  202. START_FUNC ___modqi3
  203. ;; r8 = 4[sp] % 6[sp]
  204. movw hl, sp
  205. movw de, #0
  206. mov a, [hl+4]
  207. mov1 cy, a.7
  208. bc $mod_signed_num
  209. mov a, [hl+6]
  210. mov1 cy, a.7
  211. bc $mod_signed_den
  212. br $!__generic_qimod
  213. mod_signed_num:
  214. ;; neg [sp+4]
  215. mov a, #0
  216. sub a, [hl+4]
  217. mov [hl+4], a
  218. mov d, #1
  219. mov a, [hl+6]
  220. mov1 cy, a.7
  221. bnc $mod_unsigned_den
  222. mod_signed_den:
  223. ;; neg [sp+6]
  224. mov a, #0
  225. sub a, [hl+6]
  226. mov [hl+6], a
  227. mov e, #1
  228. mod_unsigned_den:
  229. call $!__generic_qimod
  230. mov a, d
  231. cmp0 a
  232. bz $mod_no_neg
  233. mov a, #0
  234. sub a, r8
  235. mov r8, a
  236. ;; Also restore numerator
  237. movw ax, sp
  238. addw ax, #4
  239. NEG_AX
  240. mod_no_neg:
  241. mov a, e
  242. cmp0 a
  243. bz $mod_skip_restore_den
  244. movw ax, sp
  245. addw ax, #6
  246. NEG_AX
  247. mod_skip_restore_den:
  248. ret
  249. END_FUNC ___modqi3