1 1.1 mrg ################################### 2 1.1 mrg # 3 1.1.1.11 mrg # Copyright (C) 2009-2024 Free Software Foundation, Inc. 4 1.1 mrg # 5 1.1 mrg # Contributed by Michael Eager <eager@eagercon.com>. 6 1.1 mrg # 7 1.1 mrg # This file is free software; you can redistribute it and/or modify it 8 1.1 mrg # under the terms of the GNU General Public License as published by the 9 1.1 mrg # Free Software Foundation; either version 3, or (at your option) any 10 1.1 mrg # later version. 11 1.1 mrg # 12 1.1 mrg # GCC is distributed in the hope that it will be useful, but WITHOUT 13 1.1 mrg # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 1.1 mrg # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 1.1 mrg # License for more details. 16 1.1 mrg # 17 1.1 mrg # Under Section 7 of GPL version 3, you are granted additional 18 1.1 mrg # permissions described in the GCC Runtime Library Exception, version 19 1.1 mrg # 3.1, as published by the Free Software Foundation. 20 1.1 mrg # 21 1.1 mrg # You should have received a copy of the GNU General Public License and 22 1.1 mrg # a copy of the GCC Runtime Library Exception along with this program; 23 1.1 mrg # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 1.1 mrg # <http://www.gnu.org/licenses/>. 25 1.1 mrg # 26 1.1 mrg # modsi3.S 27 1.1 mrg # 28 1.1 mrg # modulo operation for 64 bit integers. 29 1.1 mrg # 30 1.1 mrg ####################################### 31 1.1 mrg 32 1.1 mrg 33 1.1.1.7 mrg /* An executable stack is *not* required for these functions. */ 34 1.1.1.7 mrg #ifdef __linux__ 35 1.1.1.7 mrg .section .note.GNU-stack,"",%progbits 36 1.1.1.7 mrg .previous 37 1.1.1.7 mrg #endif 38 1.1.1.7 mrg 39 1.1 mrg .globl __moddi3 40 1.1 mrg .ent __moddi3 41 1.1 mrg __moddi3: 42 1.1 mrg .frame r1,0,r15 43 1.1 mrg 44 1.1 mrg #Change the stack pointer value and Save callee saved regs 45 1.1 mrg addik r1,r1,-24 46 1.1 mrg swi r25,r1,0 47 1.1 mrg swi r26,r1,4 48 1.1 mrg swi r27,r1,8 # used for sign 49 1.1 mrg swi r28,r1,12 # used for loop count 50 1.1 mrg swi r29,r1,16 # Used for div value High 51 1.1 mrg swi r30,r1,20 # Used for div value Low 52 1.1 mrg 53 1.1 mrg #Check for Zero Value in the divisor/dividend 54 1.1 mrg OR r9,r5,r6 # Check for the op1 being zero 55 1.1 mrg BEQID r9,$LaResult_Is_Zero # Result is zero 56 1.1 mrg OR r9,r7,r8 # Check for the dividend being zero 57 1.1 mrg BEQI r9,$LaDiv_By_Zero # Div_by_Zero # Division Error 58 1.1 mrg BGEId r5,$La1_Pos 59 1.1 mrg XOR r27,r5,r7 # Get the sign of the result 60 1.1 mrg RSUBI r6,r6,0 # Make dividend positive 61 1.1 mrg RSUBIC r5,r5,0 # Make dividend positive 62 1.1 mrg $La1_Pos: 63 1.1 mrg BGEI r7,$La2_Pos 64 1.1 mrg RSUBI r8,r8,0 # Make Divisor Positive 65 1.1 mrg RSUBIC r9,r9,0 # Make Divisor Positive 66 1.1 mrg $La2_Pos: 67 1.1 mrg ADDIK r4,r0,0 # Clear mod low 68 1.1 mrg ADDIK r3,r0,0 # Clear mod high 69 1.1 mrg ADDIK r29,r0,0 # clear div high 70 1.1 mrg ADDIK r30,r0,0 # clear div low 71 1.1 mrg ADDIK r28,r0,64 # Initialize the loop count 72 1.1 mrg # First part try to find the first '1' in the r5/r6 73 1.1 mrg $LaDIV1: 74 1.1 mrg ADD r6,r6,r6 75 1.1 mrg ADDC r5,r5,r5 # left shift logical r5 76 1.1 mrg BGEID r5,$LaDIV1 77 1.1 mrg ADDIK r28,r28,-1 78 1.1 mrg $LaDIV2: 79 1.1 mrg ADD r6,r6,r6 80 1.1 mrg ADDC r5,r5,r5 # left shift logical r5/r6 get the '1' into the Carry 81 1.1 mrg ADDC r4,r4,r4 # Move that bit into the Mod register 82 1.1 mrg ADDC r3,r3,r3 # Move carry into high mod register 83 1.1 mrg rsub r18,r7,r3 # Compare the High Parts of Mod and Divisor 84 1.1 mrg bnei r18,$L_High_EQ 85 1.1 mrg rsub r18,r6,r4 # Compare Low Parts only if Mod[h] == Divisor[h] 86 1.1 mrg $L_High_EQ: 87 1.1 mrg rSUB r26,r8,r4 # Subtract divisor[L] from Mod[L] 88 1.1 mrg rsubc r25,r7,r3 # Subtract divisor[H] from Mod[H] 89 1.1 mrg BLTi r25,$LaMOD_TOO_SMALL 90 1.1 mrg OR r3,r0,r25 # move r25 to mod [h] 91 1.1 mrg OR r4,r0,r26 # move r26 to mod [l] 92 1.1 mrg ADDI r30,r30,1 93 1.1 mrg ADDC r29,r29,r0 94 1.1 mrg $LaMOD_TOO_SMALL: 95 1.1 mrg ADDIK r28,r28,-1 96 1.1 mrg BEQi r28,$LaLOOP_END 97 1.1 mrg ADD r30,r30,r30 # Shift in the '1' into div [low] 98 1.1 mrg ADDC r29,r29,r29 # Move the carry generated into high 99 1.1 mrg BRI $LaDIV2 # Div2 100 1.1 mrg $LaLOOP_END: 101 1.1 mrg BGEI r27,$LaRETURN_HERE 102 1.1 mrg rsubi r30,r30,0 103 1.1 mrg rsubc r29,r29,r0 104 1.1 mrg BRI $LaRETURN_HERE 105 1.1 mrg $LaDiv_By_Zero: 106 1.1 mrg $LaResult_Is_Zero: 107 1.1 mrg or r29,r0,r0 # set result to 0 [High] 108 1.1 mrg or r30,r0,r0 # set result to 0 [Low] 109 1.1 mrg $LaRETURN_HERE: 110 1.1 mrg # Restore values of CSRs and that of r29 and the divisor and the dividend 111 1.1 mrg 112 1.1 mrg lwi r25,r1,0 113 1.1 mrg lwi r26,r1,4 114 1.1 mrg lwi r27,r1,8 115 1.1 mrg lwi r28,r1,12 116 1.1 mrg lwi r29,r1,16 117 1.1 mrg lwi r30,r1,20 118 1.1 mrg rtsd r15,8 119 1.1 mrg addik r1,r1,24 120 1.1 mrg .end __moddi3 121 1.1 mrg 122