123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /* QImode div/mod functions for the GCC support library for the Renesas RL78 processors.
- Copyright (C) 2012-2022 Free Software Foundation, Inc.
- Contributed by Red Hat.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- #include "vregs.h"
- .macro MAKE_GENERIC which,need_result
- .if \need_result
- quot = r8
- num = r10
- den = r12
- bit = r14
- .else
- num = r8
- quot = r10
- den = r12
- bit = r14
- .endif
- #define bit b
- #define den c
- #define bitden bc
- START_FUNC __generic_qidivmod\which
- num_lt_den\which:
- .if \need_result
- mov r8, #0
- .else
- mov a, [hl+4]
- mov r8, a
- .endif
- ret
- num_eq_den\which:
- .if \need_result
- mov r8, #1
- .else
- mov r8, #0
- .endif
- ret
-
- den_is_zero\which:
- mov r8, #0x00
- ret
- ;; These routines leave DE alone - the signed functions use DE
- ;; to store sign information that must remain intact
- .if \need_result
- .global __generic_qidiv
- __generic_qidiv:
- .else
- .global __generic_qimod
- __generic_qimod:
- .endif
- ;; (quot,rem) = 4[hl] /% 6[hl]
- mov a, [hl+4] ; num
- cmp a, [hl+6] ; den
- bz $num_eq_den\which
- bnh $num_lt_den\which
-
- ;; copy numerator
- ; mov a, [hl+4] ; already there from above
- mov num, a
- ;; copy denomonator
- mov a, [hl+6]
- mov den, a
- cmp0 den
- bz $den_is_zero\which
- den_not_zero\which:
- .if \need_result
- ;; zero out quot
- mov quot, #0
- .endif
- ;; initialize bit to 1
- mov bit, #1
- ; while (den < num && !(den & (1L << BITS_MINUS_1)))
- shift_den_bit\which:
- .macro SDB_ONE\which
- mov a, den
- mov1 cy,a.7
- bc $enter_main_loop\which
- cmp a, num
- bh $enter_main_loop\which
- ;; den <<= 1
- ; mov a, den ; already has it from the cmpw above
- shl a, 1
- mov den, a
- ;; bit <<= 1
- shl bit, 1
- .endm
- SDB_ONE\which
- SDB_ONE\which
- br $shift_den_bit\which
- main_loop\which:
- ;; if (num >= den) (cmp den > num)
- mov a, den
- cmp a, num
- bh $next_loop\which
- ;; num -= den
- mov a, num
- sub a, den
- mov num, a
- .if \need_result
- ;; res |= bit
- mov a, quot
- or a, bit
- mov quot, a
- .endif
- next_loop\which:
- ;; den, bit >>= 1
- movw ax, bitden
- shrw ax, 1
- movw bitden, ax
- enter_main_loop\which:
- cmp0 bit
- bnz $main_loop\which
- main_loop_done\which:
- ret
- END_FUNC __generic_qidivmod\which
- .endm
- ;----------------------------------------------------------------------
- MAKE_GENERIC _d 1
- MAKE_GENERIC _m 0
- ;----------------------------------------------------------------------
- START_FUNC ___udivqi3
- ;; r8 = 4[sp] / 6[sp]
- movw hl, sp
- br $!__generic_qidiv
- END_FUNC ___udivqi3
-
- START_FUNC ___umodqi3
- ;; r8 = 4[sp] % 6[sp]
- movw hl, sp
- br $!__generic_qimod
- END_FUNC ___umodqi3
- ;----------------------------------------------------------------------
- .macro NEG_AX
- movw hl, ax
- mov a, #0
- sub a, [hl]
- mov [hl], a
- .endm
- ;----------------------------------------------------------------------
- START_FUNC ___divqi3
- ;; r8 = 4[sp] / 6[sp]
- movw hl, sp
- movw de, #0
- mov a, [sp+4]
- mov1 cy, a.7
- bc $div_signed_num
- mov a, [sp+6]
- mov1 cy, a.7
- bc $div_signed_den
- br $!__generic_qidiv
-
- div_signed_num:
- ;; neg [sp+4]
- mov a, #0
- sub a, [hl+4]
- mov [hl+4], a
- mov d, #1
- mov a, [sp+6]
- mov1 cy, a.6
- bnc $div_unsigned_den
- div_signed_den:
- ;; neg [sp+6]
- mov a, #0
- sub a, [hl+6]
- mov [hl+6], a
- mov e, #1
- div_unsigned_den:
- call $!__generic_qidiv
- mov a, d
- cmp0 a
- bz $div_skip_restore_num
- ;; We have to restore the numerator [sp+4]
- movw ax, sp
- addw ax, #4
- NEG_AX
- mov a, d
- div_skip_restore_num:
- xor a, e
- bz $div_no_neg
- movw ax, #r8
- NEG_AX
- div_no_neg:
- mov a, e
- cmp0 a
- bz $div_skip_restore_den
- movw ax, sp
- addw ax, #6
- NEG_AX
- div_skip_restore_den:
- ret
- END_FUNC ___divqi3
-
- START_FUNC ___modqi3
- ;; r8 = 4[sp] % 6[sp]
- movw hl, sp
- movw de, #0
- mov a, [hl+4]
- mov1 cy, a.7
- bc $mod_signed_num
- mov a, [hl+6]
- mov1 cy, a.7
- bc $mod_signed_den
- br $!__generic_qimod
-
- mod_signed_num:
- ;; neg [sp+4]
- mov a, #0
- sub a, [hl+4]
- mov [hl+4], a
- mov d, #1
- mov a, [hl+6]
- mov1 cy, a.7
- bnc $mod_unsigned_den
- mod_signed_den:
- ;; neg [sp+6]
- mov a, #0
- sub a, [hl+6]
- mov [hl+6], a
- mov e, #1
- mod_unsigned_den:
- call $!__generic_qimod
- mov a, d
- cmp0 a
- bz $mod_no_neg
- mov a, #0
- sub a, r8
- mov r8, a
- ;; Also restore numerator
- movw ax, sp
- addw ax, #4
- NEG_AX
- mod_no_neg:
- mov a, e
- cmp0 a
- bz $mod_skip_restore_den
- movw ax, sp
- addw ax, #6
- NEG_AX
- mod_skip_restore_den:
- ret
- END_FUNC ___modqi3
|