Home | History | Annotate | Line # | Download | only in riscv
      1 /* Integer division routines for RISC-V.
      2 
      3    Copyright (C) 2016-2022 Free Software Foundation, Inc.
      4 
      5 This file is part of GCC.
      6 
      7 GCC is free software; you can redistribute it and/or modify it under
      8 the terms of the GNU General Public License as published by the Free
      9 Software Foundation; either version 3, or (at your option) any later
     10 version.
     11 
     12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15 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 "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
     38 FUNC_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    HIDDEN_JUMPTARGET(__udivdi3)
     44   sext.w a0, a0
     45   jr     t0
     46 FUNC_END (__udivsi3)
     47 
     48 FUNC_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    HIDDEN_JUMPTARGET(__udivdi3)
     56   sext.w a0, a1
     57   jr     t0
     58 FUNC_END (__umodsi3)
     59 
     60 FUNC_ALIAS (__modsi3, __moddi3)
     61 
     62 FUNC_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 
     68 FUNC_BEGIN (__divdi3)
     69   bltz  a0, .L10
     70   bltz  a1, .L11
     71   /* Since the quotient is positive, fall into __udivdi3.  */
     72 
     73 FUNC_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
     97 FUNC_END (__udivdi3)
     98 HIDDEN_DEF (__udivdi3)
     99 
    100 FUNC_BEGIN (__umoddi3)
    101   /* Call __udivdi3(a0, a1), then return the remainder, which is in a1.  */
    102   move  t0, ra
    103   jal   HIDDEN_JUMPTARGET(__udivdi3)
    104   move  a0, a1
    105   jr    t0
    106 FUNC_END (__umoddi3)
    107 
    108   /* Handle negative arguments to __divdi3.  */
    109 .L10:
    110   neg   a0, a0
    111   /* Zero is handled as a negative so that the result will not be inverted.  */
    112   bgtz  a1, .L12     /* Compute __udivdi3(-a0, a1), then negate the result.  */
    113 
    114   neg   a1, a1
    115   j     HIDDEN_JUMPTARGET(__udivdi3)     /* Compute __udivdi3(-a0, -a1).  */
    116 .L11:                /* Compute __udivdi3(a0, -a1), then negate the result.  */
    117   neg   a1, a1
    118 .L12:
    119   move  t0, ra
    120   jal   HIDDEN_JUMPTARGET(__udivdi3)
    121   neg   a0, a0
    122   jr    t0
    123 FUNC_END (__divdi3)
    124 
    125 FUNC_BEGIN (__moddi3)
    126   move   t0, ra
    127   bltz   a1, .L31
    128   bltz   a0, .L32
    129 .L30:
    130   jal    HIDDEN_JUMPTARGET(__udivdi3)    /* The dividend is not negative.  */
    131   move   a0, a1
    132   jr     t0
    133 .L31:
    134   neg    a1, a1
    135   bgez   a0, .L30
    136 .L32:
    137   neg    a0, a0
    138   jal    HIDDEN_JUMPTARGET(__udivdi3)    /* The dividend is hella negative.  */
    139   neg    a0, a1
    140   jr     t0
    141 FUNC_END (__moddi3)
    142 
    143 #if __riscv_xlen == 64
    144   /* continuation of __divsi3 */
    145 .L20:
    146   sll   t0, t0, 31
    147   bne   a0, t0, __divdi3
    148   ret
    149 FUNC_END (__divsi3)
    150 #endif
    151