aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc/config/microblaze/modsi3.S
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgcc/config/microblaze/modsi3.S')
-rw-r--r--gcc-4.9/libgcc/config/microblaze/modsi3.S95
1 files changed, 95 insertions, 0 deletions
diff --git a/gcc-4.9/libgcc/config/microblaze/modsi3.S b/gcc-4.9/libgcc/config/microblaze/modsi3.S
new file mode 100644
index 000000000..73951eccf
--- /dev/null
+++ b/gcc-4.9/libgcc/config/microblaze/modsi3.S
@@ -0,0 +1,95 @@
+###################################
+#
+# Copyright (C) 2009-2014 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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
+# <http://www.gnu.org/licenses/>.
+#
+# modsi3.S
+#
+# modulo operation for 32 bit integers.
+# Input : op1 in Reg r5
+# op2 in Reg r6
+# Output: op1 mod op2 in Reg r3
+#
+#######################################
+
+ .globl __modsi3
+ .ent __modsi3
+ .type __modsi3,@function
+__modsi3:
+ .frame r1,0,r15
+
+ addik r1,r1,-16
+ swi r28,r1,0
+ swi r29,r1,4
+ swi r30,r1,8
+ swi r31,r1,12
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQI r5,$LaResult_Is_Zero # Result is Zero
+ BGEId r5,$LaR5_Pos
+ ADD r28,r5,r0 # Get the sign of the result [ Depends only on the first arg]
+ RSUBI r5,r5,0 # Make r5 positive
+$LaR5_Pos:
+ BGEI r6,$LaR6_Pos
+ RSUBI r6,r6,0 # Make r6 positive
+$LaR6_Pos:
+ ADDIK r3,r0,0 # Clear mod
+ ADDIK r30,r0,0 # clear div
+ BLTId r5,$LaDIV2 # If r5 is still negative (0x80000000), skip
+ # the first bit search.
+ ADDIK r29,r0,32 # Initialize the loop count
+ # First part try to find the first '1' in the r5
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGEID r5,$LaDIV1 #
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r3,r3,r3 # Move that bit into the Mod register
+ rSUB r31,r6,r3 # Try to subtract (r30 a r6)
+ BLTi r31,$LaMOD_TOO_SMALL
+ OR r3,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r30,r30,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r30,r30,r30 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BGEI r28,$LaRETURN_HERE
+ BRId $LaRETURN_HERE
+ rsubi r3,r3,0 # Negate the result
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ or r3,r0,r0 # set result to 0 [Both mod as well as div are 0]
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ lwi r28,r1,0
+ lwi r29,r1,4
+ lwi r30,r1,8
+ lwi r31,r1,12
+ rtsd r15,8
+ addik r1,r1,16
+ .end __modsi3
+ .size __modsi3, . - __modsi3
+