/* QImode div/mod functions for the GCC support library for the Renesas RL78 processors. Copyright (C) 2012-2014 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 . */ #ifndef __RL78_G10__ #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 #if 1 #define bit b #define den c #define bitden bc #endif 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, #0xff ret ;; These routines leave DE alone - the signed functions use DE ;; to store sign information that must remain intact .if \need_result generic_div: .else generic_mod: .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 .endm make_generic _d 1 make_generic _m 0 ;---------------------------------------------------------------------- .global ___udivqi3 .type ___udivqi3,@function ___udivqi3: ;; r8 = 4[sp] / 6[sp] movw hl, sp br $!generic_div .size ___udivqi3, . - ___udivqi3 .global ___umodqi3 .type ___umodqi3,@function ___umodqi3: ;; r8 = 4[sp] % 6[sp] movw hl, sp br $!generic_mod .size ___umodqi3, . - ___umodqi3 ;---------------------------------------------------------------------- .macro neg_ax movw hl, ax mov a, #0 sub a, [hl] mov [hl], a .endm .global ___divqi3 .type ___divqi3,@function ___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_div 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_div 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 .size ___divqi3, . - ___divqi3 .global ___modqi3 .type ___modqi3,@function ___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_mod 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_mod 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 .size ___modqi3, . - ___modqi3 #endif