Retro68/gcc/libgcc/config/rl78/divmodqi.S

306 lines
5.1 KiB
ArmAsm
Raw Normal View History

2014-09-21 17:33:12 +00:00
/* QImode div/mod functions for the GCC support library for the Renesas RL78 processors.
2019-06-02 15:48:37 +00:00
Copyright (C) 2012-2019 Free Software Foundation, Inc.
2014-09-21 17:33:12 +00:00
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"
2015-08-28 15:33:40 +00:00
.macro MAKE_GENERIC which,need_result
2014-09-21 17:33:12 +00:00
.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
2015-08-28 15:33:40 +00:00
START_FUNC __generic_qidivmod\which
2014-09-21 17:33:12 +00:00
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:
2017-04-10 11:32:00 +00:00
mov r8, #0x00
2014-09-21 17:33:12 +00:00
ret
;; These routines leave DE alone - the signed functions use DE
;; to store sign information that must remain intact
.if \need_result
2015-08-28 15:33:40 +00:00
.global __generic_qidiv
__generic_qidiv:
2014-09-21 17:33:12 +00:00
.else
2015-08-28 15:33:40 +00:00
.global __generic_qimod
__generic_qimod:
2014-09-21 17:33:12 +00:00
.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:
2015-08-28 15:33:40 +00:00
.macro SDB_ONE\which
2014-09-21 17:33:12 +00:00
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
2015-08-28 15:33:40 +00:00
.endm
2014-09-21 17:33:12 +00:00
2015-08-28 15:33:40 +00:00
SDB_ONE\which
SDB_ONE\which
2014-09-21 17:33:12 +00:00
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
2015-08-28 15:33:40 +00:00
END_FUNC __generic_qidivmod\which
.endm
2014-09-21 17:33:12 +00:00
2015-08-28 15:33:40 +00:00
;----------------------------------------------------------------------
MAKE_GENERIC _d 1
MAKE_GENERIC _m 0
2014-09-21 17:33:12 +00:00
;----------------------------------------------------------------------
2015-08-28 15:33:40 +00:00
START_FUNC ___udivqi3
2014-09-21 17:33:12 +00:00
;; r8 = 4[sp] / 6[sp]
movw hl, sp
2015-08-28 15:33:40 +00:00
br $!__generic_qidiv
END_FUNC ___udivqi3
2014-09-21 17:33:12 +00:00
2015-08-28 15:33:40 +00:00
START_FUNC ___umodqi3
2014-09-21 17:33:12 +00:00
;; r8 = 4[sp] % 6[sp]
movw hl, sp
2015-08-28 15:33:40 +00:00
br $!__generic_qimod
END_FUNC ___umodqi3
2014-09-21 17:33:12 +00:00
;----------------------------------------------------------------------
2015-08-28 15:33:40 +00:00
.macro NEG_AX
2014-09-21 17:33:12 +00:00
movw hl, ax
mov a, #0
sub a, [hl]
mov [hl], a
2015-08-28 15:33:40 +00:00
.endm
;----------------------------------------------------------------------
2014-09-21 17:33:12 +00:00
2015-08-28 15:33:40 +00:00
START_FUNC ___divqi3
2014-09-21 17:33:12 +00:00
;; 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
2015-08-28 15:33:40 +00:00
br $!__generic_qidiv
2014-09-21 17:33:12 +00:00
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:
2015-08-28 15:33:40 +00:00
call $!__generic_qidiv
2014-09-21 17:33:12 +00:00
mov a, d
cmp0 a
bz $div_skip_restore_num
;; We have to restore the numerator [sp+4]
movw ax, sp
addw ax, #4
2015-08-28 15:33:40 +00:00
NEG_AX
2014-09-21 17:33:12 +00:00
mov a, d
div_skip_restore_num:
xor a, e
bz $div_no_neg
movw ax, #r8
2015-08-28 15:33:40 +00:00
NEG_AX
2014-09-21 17:33:12 +00:00
div_no_neg:
mov a, e
cmp0 a
bz $div_skip_restore_den
movw ax, sp
addw ax, #6
2015-08-28 15:33:40 +00:00
NEG_AX
2014-09-21 17:33:12 +00:00
div_skip_restore_den:
ret
2015-08-28 15:33:40 +00:00
END_FUNC ___divqi3
2014-09-21 17:33:12 +00:00
2015-08-28 15:33:40 +00:00
START_FUNC ___modqi3
2014-09-21 17:33:12 +00:00
;; 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
2015-08-28 15:33:40 +00:00
br $!__generic_qimod
2014-09-21 17:33:12 +00:00
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:
2015-08-28 15:33:40 +00:00
call $!__generic_qimod
2014-09-21 17:33:12 +00:00
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
2015-08-28 15:33:40 +00:00
NEG_AX
2014-09-21 17:33:12 +00:00
mod_no_neg:
mov a, e
cmp0 a
bz $mod_skip_restore_den
movw ax, sp
addw ax, #6
2015-08-28 15:33:40 +00:00
NEG_AX
2014-09-21 17:33:12 +00:00
mod_skip_restore_den:
ret
2015-08-28 15:33:40 +00:00
END_FUNC ___modqi3