1/* Integer division routines for RISC-V. 2 3 Copyright (C) 2016-2020 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17Under Section 7 of GPL version 3, you are granted additional 18permissions described in the GCC Runtime Library Exception, version 193.1, as published by the Free Software Foundation. 20 21You should have received a copy of the GNU General Public License and 22a copy of the GCC Runtime Library Exception along with this program; 23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24<http://www.gnu.org/licenses/>. */ 25 26#include "riscv-asm.h" 27 28 .text 29 .align 2 30 31#if __riscv_xlen == 32 32/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */ 33# define __udivdi3 __udivsi3 34# define __umoddi3 __umodsi3 35# define __divdi3 __divsi3 36# define __moddi3 __modsi3 37#else 38FUNC_BEGIN (__udivsi3) 39 /* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t. */ 40 sll a0, a0, 32 41 sll a1, a1, 32 42 move t0, ra 43 jal __udivdi3 44 sext.w a0, a0 45 jr t0 46FUNC_END (__udivsi3) 47 48FUNC_BEGIN (__umodsi3) 49 /* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t. */ 50 sll a0, a0, 32 51 sll a1, a1, 32 52 srl a0, a0, 32 53 srl a1, a1, 32 54 move t0, ra 55 jal __udivdi3 56 sext.w a0, a1 57 jr t0 58FUNC_END (__umodsi3) 59 60FUNC_ALIAS (__modsi3, __moddi3) 61 62FUNC_BEGIN( __divsi3) 63 /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */ 64 li t0, -1 65 beq a1, t0, .L20 66#endif 67 68FUNC_BEGIN (__divdi3) 69 bltz a0, .L10 70 bltz a1, .L11 71 /* Since the quotient is positive, fall into __udivdi3. */ 72 73FUNC_BEGIN (__udivdi3) 74 mv a2, a1 75 mv a1, a0 76 li a0, -1 77 beqz a2, .L5 78 li a3, 1 79 bgeu a2, a1, .L2 80.L1: 81 blez a2, .L2 82 slli a2, a2, 1 83 slli a3, a3, 1 84 bgtu a1, a2, .L1 85.L2: 86 li a0, 0 87.L3: 88 bltu a1, a2, .L4 89 sub a1, a1, a2 90 or a0, a0, a3 91.L4: 92 srli a3, a3, 1 93 srli a2, a2, 1 94 bnez a3, .L3 95.L5: 96 ret 97FUNC_END (__udivdi3) 98 99FUNC_BEGIN (__umoddi3) 100 /* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */ 101 move t0, ra 102 jal __udivdi3 103 move a0, a1 104 jr t0 105FUNC_END (__umoddi3) 106 107 /* Handle negative arguments to __divdi3. */ 108.L10: 109 neg a0, a0 110 bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */ 111 neg a1, a1 112 j __udivdi3 /* Compute __udivdi3(-a0, -a1). */ 113.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */ 114 neg a1, a1 115.L12: 116 move t0, ra 117 jal __udivdi3 118 neg a0, a0 119 jr t0 120FUNC_END (__divdi3) 121 122FUNC_BEGIN (__moddi3) 123 move t0, ra 124 bltz a1, .L31 125 bltz a0, .L32 126.L30: 127 jal __udivdi3 /* The dividend is not negative. */ 128 move a0, a1 129 jr t0 130.L31: 131 neg a1, a1 132 bgez a0, .L30 133.L32: 134 neg a0, a0 135 jal __udivdi3 /* The dividend is hella negative. */ 136 neg a0, a1 137 jr t0 138FUNC_END (__moddi3) 139 140#if __riscv_xlen == 64 141 /* continuation of __divsi3 */ 142.L20: 143 sll t0, t0, 31 144 bne a0, t0, __divdi3 145 ret 146FUNC_END (__divsi3) 147#endif 148