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