···11+#include <linux/module.h>22+33+#include "libgcc.h"44+55+long long __ashrdi3(long long u, word_type b)66+{77+ DWunion uu, w;88+ word_type bm;99+1010+ if (b == 0)1111+ return u;1212+1313+ uu.ll = u;1414+ bm = 32 - b;1515+1616+ if (bm <= 0) {1717+ /* w.s.high = 1..1 or 0..0 */1818+ w.s.high =1919+ uu.s.high >> 31;2020+ w.s.low = uu.s.high >> -bm;2121+ } else {2222+ const unsigned int carries = (unsigned int) uu.s.high << bm;2323+2424+ w.s.high = uu.s.high >> b;2525+ w.s.low = ((unsigned int) uu.s.low >> b) | carries;2626+ }2727+2828+ return w.ll;2929+}3030+3131+EXPORT_SYMBOL(__ashrdi3);
+73
arch/microblaze/lib/divsi3.S
···11+#include <linux/linkage.h>22+33+/*44+* Divide operation for 32 bit integers.55+* Input : Dividend in Reg r566+* Divisor in Reg r677+* Output: Result in Reg r388+*/99+ .text1010+ .globl __divsi31111+ .type __divsi3, @function1212+ .ent __divsi31313+__divsi3:1414+ .frame r1, 0, r151515+1616+ addik r1, r1, -161717+ swi r28, r1, 01818+ swi r29, r1, 41919+ swi r30, r1, 82020+ swi r31, r1, 122121+2222+ beqi r6, div_by_zero /* div_by_zero - division error */2323+ beqi r5, result_is_zero /* result is zero */2424+ bgeid r5, r5_pos2525+ xor r28, r5, r6 /* get the sign of the result */2626+ rsubi r5, r5, 0 /* make r5 positive */2727+r5_pos:2828+ bgei r6, r6_pos2929+ rsubi r6, r6, 0 /* make r6 positive */3030+r6_pos:3131+ addik r30, r0, 0 /* clear mod */3232+ addik r3, r0, 0 /* clear div */3333+ addik r29, r0, 32 /* initialize the loop count */3434+3535+ /* first part try to find the first '1' in the r5 */3636+div0:3737+ blti r5, div2 /* this traps r5 == 0x80000000 */3838+div1:3939+ add r5, r5, r5 /* left shift logical r5 */4040+ bgtid r5, div14141+ addik r29, r29, -14242+div2:4343+ /* left shift logical r5 get the '1' into the carry */4444+ add r5, r5, r54545+ addc r30, r30, r30 /* move that bit into the mod register */4646+ rsub r31, r6, r30 /* try to subtract (r30 a r6) */4747+ blti r31, mod_too_small4848+ /* move the r31 to mod since the result was positive */4949+ or r30, r0, r315050+ addik r3, r3, 15151+mod_too_small:5252+ addik r29, r29, -15353+ beqi r29, loop_end5454+ add r3, r3, r3 /* shift in the '1' into div */5555+ bri div2 /* div2 */5656+loop_end:5757+ bgei r28, return_here5858+ brid return_here5959+ rsubi r3, r3, 0 /* negate the result */6060+div_by_zero:6161+result_is_zero:6262+ or r3, r0, r0 /* set result to 0 */6363+return_here:6464+/* restore values of csrs and that of r3 and the divisor and the dividend */6565+ lwi r28, r1, 06666+ lwi r29, r1, 46767+ lwi r30, r1, 86868+ lwi r31, r1, 126969+ rtsd r15, 87070+ addik r1, r1, 167171+7272+.size __divsi3, . - __divsi37373+.end __divsi3
+25
arch/microblaze/lib/libgcc.h
···11+#ifndef __ASM_LIBGCC_H22+#define __ASM_LIBGCC_H33+44+#include <asm/byteorder.h>55+66+typedef int word_type __attribute__ ((mode (__word__)));77+88+#ifdef __BIG_ENDIAN99+struct DWstruct {1010+ int high, low;1111+};1212+#elif defined(__LITTLE_ENDIAN)1313+struct DWstruct {1414+ int low, high;1515+};1616+#else1717+#error I feel sick.1818+#endif1919+2020+typedef union {2121+ struct DWstruct s;2222+ long long ll;2323+} DWunion;2424+2525+#endif /* __ASM_LIBGCC_H */
···11+#include <linux/linkage.h>22+33+/*44+* modulo operation for 32 bit integers.55+* Input : op1 in Reg r566+* op2 in Reg r677+* Output: op1 mod op2 in Reg r388+*/99+1010+ .text1111+ .globl __modsi31212+ .type __modsi3, @function1313+ .ent __modsi31414+1515+__modsi3:1616+ .frame r1, 0, r151717+1818+ addik r1, r1, -161919+ swi r28, r1, 02020+ swi r29, r1, 42121+ swi r30, r1, 82222+ swi r31, r1, 122323+2424+ beqi r6, div_by_zero /* div_by_zero division error */2525+ beqi r5, result_is_zero /* result is zero */2626+ bgeid r5, r5_pos2727+ /* get the sign of the result [ depends only on the first arg] */2828+ add r28, r5, r02929+ rsubi r5, r5, 0 /* make r5 positive */3030+r5_pos:3131+ bgei r6, r6_pos3232+ rsubi r6, r6, 0 /* make r6 positive */3333+r6_pos:3434+ addik r3, r0, 0 /* clear mod */3535+ addik r30, r0, 0 /* clear div */3636+ addik r29, r0, 32 /* initialize the loop count */3737+/* first part try to find the first '1' in the r5 */3838+div1:3939+ add r5, r5, r5 /* left shift logical r5 */4040+ bgeid r5, div14141+ addik r29, r29, -14242+div2:4343+ /* left shift logical r5 get the '1' into the carry */4444+ add r5, r5, r54545+ addc r3, r3, r3 /* move that bit into the mod register */4646+ rsub r31, r6, r3 /* try to subtract (r30 a r6) */4747+ blti r31, mod_too_small4848+ /* move the r31 to mod since the result was positive */4949+ or r3, r0, r315050+ addik r30, r30, 15151+mod_too_small:5252+ addik r29, r29, -15353+ beqi r29, loop_end5454+ add r30, r30, r30 /* shift in the '1' into div */5555+ bri div2 /* div2 */5656+loop_end:5757+ bgei r28, return_here5858+ brid return_here5959+ rsubi r3, r3, 0 /* negate the result */6060+div_by_zero:6161+result_is_zero:6262+ or r3, r0, r0 /* set result to 0 [both mod as well as div are 0] */6363+return_here:6464+/* restore values of csrs and that of r3 and the divisor and the dividend */6565+ lwi r28, r1, 06666+ lwi r29, r1, 46767+ lwi r30, r1, 86868+ lwi r31, r1, 126969+ rtsd r15, 87070+ addik r1, r1, 167171+7272+.size __modsi3, . - __modsi37373+.end __modsi3
+121
arch/microblaze/lib/muldi3.S
···11+#include <linux/linkage.h>22+33+/*44+ * Multiply operation for 64 bit integers, for devices with hard multiply55+ * Input : Operand1[H] in Reg r566+ * Operand1[L] in Reg r677+ * Operand2[H] in Reg r788+ * Operand2[L] in Reg r899+ * Output: Result[H] in Reg r31010+ * Result[L] in Reg r41111+ *1212+ * Explaination:1313+ *1414+ * Both the input numbers are divided into 16 bit number as follows1515+ * op1 = A B C D1616+ * op2 = E F G H1717+ * result = D * H1818+ * + (C * H + D * G) << 161919+ * + (B * H + C * G + D * F) << 322020+ * + (A * H + B * G + C * F + D * E) << 482121+ *2222+ * Only 64 bits of the output are considered2323+ */2424+2525+ .text2626+ .globl __muldi32727+ .type __muldi3, @function2828+ .ent __muldi32929+3030+__muldi3:3131+ addi r1, r1, -403232+3333+/* Save the input operands on the caller's stack */3434+ swi r5, r1, 443535+ swi r6, r1, 483636+ swi r7, r1, 523737+ swi r8, r1, 563838+3939+/* Store all the callee saved registers */4040+ sw r20, r1, r04141+ swi r21, r1, 44242+ swi r22, r1, 84343+ swi r23, r1, 124444+ swi r24, r1, 164545+ swi r25, r1, 204646+ swi r26, r1, 244747+ swi r27, r1, 284848+4949+/* Load all the 16 bit values for A thru H */5050+ lhui r20, r1, 44 /* A */5151+ lhui r21, r1, 46 /* B */5252+ lhui r22, r1, 48 /* C */5353+ lhui r23, r1, 50 /* D */5454+ lhui r24, r1, 52 /* E */5555+ lhui r25, r1, 54 /* F */5656+ lhui r26, r1, 56 /* G */5757+ lhui r27, r1, 58 /* H */5858+5959+/* D * H ==> LSB of the result on stack ==> Store1 */6060+ mul r9, r23, r276161+ swi r9, r1, 36 /* Pos2 and Pos3 */6262+6363+/* Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2 */6464+/* Store the carry generated in position 2 for Pos 3 */6565+ lhui r11, r1, 36 /* Pos2 */6666+ mul r9, r22, r27 /* C * H */6767+ mul r10, r23, r26 /* D * G */6868+ add r9, r9, r106969+ addc r12, r0, r07070+ add r9, r9, r117171+ addc r12, r12, r0 /* Store the Carry */7272+ shi r9, r1, 36 /* Store Pos2 */7373+ swi r9, r1, 327474+ lhui r11, r1, 327575+ shi r11, r1, 34 /* Store Pos1 */7676+7777+/* Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1 */7878+ mul r9, r21, r27 /* B * H */7979+ mul r10, r22, r26 /* C * G */8080+ mul r7, r23, r25 /* D * F */8181+ add r9, r9, r118282+ add r9, r9, r108383+ add r9, r9, r78484+ swi r9, r1, 32 /* Pos0 and Pos1 */8585+8686+/* Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0 */8787+ lhui r11, r1, 32 /* Pos0 */8888+ mul r9, r20, r27 /* A * H */8989+ mul r10, r21, r26 /* B * G */9090+ mul r7, r22, r25 /* C * F */9191+ mul r8, r23, r24 /* D * E */9292+ add r9, r9, r119393+ add r9, r9, r109494+ add r9, r9, r79595+ add r9, r9, r89696+ sext16 r9, r9 /* Sign extend the MSB */9797+ shi r9, r1, 329898+9999+/* Move results to r3 and r4 */100100+ lhui r3, r1, 32101101+ add r3, r3, r12102102+ shi r3, r1, 32103103+ lwi r3, r1, 32 /* Hi Part */104104+ lwi r4, r1, 36 /* Lo Part */105105+106106+/* Restore Callee saved registers */107107+ lw r20, r1, r0108108+ lwi r21, r1, 4109109+ lwi r22, r1, 8110110+ lwi r23, r1, 12111111+ lwi r24, r1, 16112112+ lwi r25, r1, 20113113+ lwi r26, r1, 24114114+ lwi r27, r1, 28115115+116116+/* Restore Frame and return */117117+ rtsd r15, 8118118+ addi r1, r1, 40119119+120120+.size __muldi3, . - __muldi3121121+.end __muldi3
+46
arch/microblaze/lib/mulsi3.S
···11+#include <linux/linkage.h>22+33+/*44+ * Multiply operation for 32 bit integers.55+ * Input : Operand1 in Reg r566+ * Operand2 in Reg r677+ * Output: Result [op1 * op2] in Reg r388+ */99+ .text1010+ .globl __mulsi31111+ .type __mulsi3, @function1212+ .ent __mulsi31313+1414+__mulsi3:1515+ .frame r1, 0, r151616+ add r3, r0, r01717+ beqi r5, result_is_zero /* multiply by zero */1818+ beqi r6, result_is_zero /* multiply by zero */1919+ bgeid r5, r5_pos2020+ xor r4, r5, r6 /* get the sign of the result */2121+ rsubi r5, r5, 0 /* make r5 positive */2222+r5_pos:2323+ bgei r6, r6_pos2424+ rsubi r6, r6, 0 /* make r6 positive */2525+r6_pos:2626+ bri l12727+l2:2828+ add r5, r5, r52929+l1:3030+ srl r6, r63131+ addc r7, r0, r03232+ beqi r7, l23333+ bneid r6, l23434+ add r3, r3, r53535+ blti r4, negateresult3636+ rtsd r15, 83737+ nop3838+negateresult:3939+ rtsd r15, 84040+ rsub r3, r3, r04141+result_is_zero:4242+ rtsd r15, 84343+ addi r3, r0, 04444+4545+.size __mulsi3, . - __mulsi34646+.end __mulsi3
+84
arch/microblaze/lib/udivsi3.S
···11+#include <linux/linkage.h>22+33+/*44+* Unsigned divide operation.55+* Input : Divisor in Reg r566+* Dividend in Reg r677+* Output: Result in Reg r388+*/99+1010+ .text1111+ .globl __udivsi31212+ .type __udivsi3, @function1313+ .ent __udivsi31414+1515+__udivsi3:1616+1717+ .frame r1, 0, r151818+1919+ addik r1, r1, -122020+ swi r29, r1, 02121+ swi r30, r1, 42222+ swi r31, r1, 82323+2424+ beqi r6, div_by_zero /* div_by_zero /* division error */2525+ beqid r5, result_is_zero /* result is zero */2626+ addik r30, r0, 0 /* clear mod */2727+ addik r29, r0, 32 /* initialize the loop count */2828+2929+/* check if r6 and r5 are equal - if yes, return 1 */3030+ rsub r18, r5, r63131+ beqid r18, return_here3232+ addik r3, r0, 13333+3434+/* check if (uns)r6 is greater than (uns)r5. in that case, just return 0 */3535+ xor r18, r5, r63636+ bgeid r18, 163737+ add r3, r0, r0 /* we would anyways clear r3 */3838+ blti r6, return_here /* r6[bit 31 = 1] hence is greater */3939+ bri checkr64040+ rsub r18, r6, r5 /* microblazecmp */4141+ blti r18, return_here4242+4343+/* if r6 [bit 31] is set, then return result as 1 */4444+checkr6:4545+ bgti r6, div04646+ brid return_here4747+ addik r3, r0, 14848+4949+/* first part try to find the first '1' in the r5 */5050+div0:5151+ blti r5, div25252+div1:5353+ add r5, r5, r5 /* left shift logical r5 */5454+ bgtid r5, div15555+ addik r29, r29, -15656+div2:5757+/* left shift logical r5 get the '1' into the carry */5858+ add r5, r5, r55959+ addc r30, r30, r30 /* move that bit into the mod register */6060+ rsub r31, r6, r30 /* try to subtract (r30 a r6) */6161+ blti r31, mod_too_small6262+/* move the r31 to mod since the result was positive */6363+ or r30, r0, r316464+ addik r3, r3, 16565+mod_too_small:6666+ addik r29, r29, -16767+ beqi r29, loop_end6868+ add r3, r3, r3 /* shift in the '1' into div */6969+ bri div2 /* div2 */7070+loop_end:7171+ bri return_here7272+div_by_zero:7373+result_is_zero:7474+ or r3, r0, r0 /* set result to 0 */7575+return_here:7676+/* restore values of csrs and that of r3 and the divisor and the dividend */7777+ lwi r29, r1, 07878+ lwi r30, r1, 47979+ lwi r31, r1, 88080+ rtsd r15, 88181+ addik r1, r1, 128282+8383+.size __udivsi3, . - __udivsi38484+.end __udivsi3
+86
arch/microblaze/lib/umodsi3.S
···11+#include <linux/linkage.h>22+33+/*44+ * Unsigned modulo operation for 32 bit integers.55+ * Input : op1 in Reg r566+ * op2 in Reg r677+ * Output: op1 mod op2 in Reg r388+ */99+1010+ .text1111+ .globl __umodsi31212+ .type __umodsi3, @function1313+ .ent __umodsi31414+1515+__umodsi3:1616+ .frame r1, 0, r151717+1818+ addik r1, r1, -121919+ swi r29, r1, 02020+ swi r30, r1, 42121+ swi r31, r1, 82222+2323+ beqi r6, div_by_zero /* div_by_zero - division error */2424+ beqid r5, result_is_zero /* result is zero */2525+ addik r3, r0, 0 /* clear div */2626+ addik r30, r0, 0 /* clear mod */2727+ addik r29, r0, 32 /* initialize the loop count */2828+2929+/* check if r6 and r5 are equal /* if yes, return 0 */3030+ rsub r18, r5, r63131+ beqi r18, return_here3232+3333+/* check if (uns)r6 is greater than (uns)r5. in that case, just return r5 */3434+ xor r18, r5, r63535+ bgeid r18, 163636+ addik r3, r5, 03737+ blti r6, return_here3838+ bri $lcheckr63939+ rsub r18, r5, r6 /* microblazecmp */4040+ bgti r18, return_here4141+4242+/* if r6 [bit 31] is set, then return result as r5-r6 */4343+$lcheckr6:4444+ bgtid r6, div04545+ addik r3, r0, 04646+ addik r18, r0, 0x7fffffff4747+ and r5, r5, r184848+ and r6, r6, r184949+ brid return_here5050+ rsub r3, r6, r55151+/* first part: try to find the first '1' in the r5 */5252+div0:5353+ blti r5, div25454+div1:5555+ add r5, r5, r5 /* left shift logical r5 */5656+ bgeid r5, div15757+ addik r29, r29, -15858+div2:5959+ /* left shift logical r5 get the '1' into the carry */6060+ add r5, r5, r56161+ addc r3, r3, r3 /* move that bit into the mod register */6262+ rsub r31, r6, r3 /* try to subtract (r3 a r6) */6363+ blti r31, mod_too_small6464+ /* move the r31 to mod since the result was positive */6565+ or r3, r0, r316666+ addik r30, r30, 16767+mod_too_small:6868+ addik r29, r29, -16969+ beqi r29, loop_end7070+ add r30, r30, r30 /* shift in the '1' into div */7171+ bri div2 /* div2 */7272+loop_end:7373+ bri return_here7474+div_by_zero:7575+result_is_zero:7676+ or r3, r0, r0 /* set result to 0 */7777+return_here:7878+/* restore values of csrs and that of r3 and the divisor and the dividend */7979+ lwi r29, r1, 08080+ lwi r30, r1, 48181+ lwi r31, r1, 88282+ rtsd r15, 88383+ addik r1, r1, 128484+8585+.size __umodsi3, . - __umodsi38686+.end __umodsi3