1/*- 2 * Copyright (c) 2012 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Matt Thomas of 3am Software Foundry. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <machine/asm.h> 31 32#ifdef __ARMEB__ 33#define ALO r1 /* incoming numerator, outgoing quotient */ 34#define AHI r0 /* incoming numerator, outgoing quotient */ 35#define BLO r3 /* incoming denominator, outgoing remainder */ 36#define BHI r2 /* incoming denominator, outgoing remainder */ 37#else 38#define ALO r0 /* incoming numerator, outgoing quotient */ 39#define AHI r1 /* incoming numerator, outgoing quotient */ 40#define BLO r2 /* incoming denominator, outgoing remainder */ 41#define BHI r3 /* incoming denominator, outgoing remainder */ 42#endif 43 44ENTRY(__aeabi_ldivmod) 45 push {r4-r6, lr} 46#define NEG r5 47 movs NEG, #0 48 49 cmp BHI, #0 50 bge 2f 51 movs NEG, #1 /* flip quotient sign */ 52 bl .Lnegate_b 53 bcs .Lmaxdenom 54 552: 56 cmp AHI, #0 57 eorlt NEG, NEG, #3 /* flip quotient sign, flip remainder sign */ 58 bllt .Lnegate_a 59 60 /* 61 * Arguments are setup, allocate some stack for the remainder 62 * and call __qdivrem for the heavy lifting. 63 */ 64 sub sp, sp, #16 65 adds r4, sp, #8 66 str r4, [sp] 67 bl __qdivrem 68 add sp, sp, #8 69 70 /* 71 * The quotient is already in the right place and neither value 72 * needs its sign flipped. 73 */ 74 cmp NEG, #0 /* any signs to flip? */ 75 beq .Lnegate_neither 76 77 cmp NEG, #2 /* does remainder need to be negative? */ 78 beq .Lnegate_b_only /* 2 means b only */ 79 bgt .Lnegate_both /* 3 means both */ 80.Lnegate_a_only: 81 bl .Lnegate_a /* 1 means a only */ 82.Lnegate_neither: 83 pop {r2-r6, pc} /* grab b from stack */ 84.Lnegate_both: 85 bl .Lnegate_a 86.Lnegate_b_only: 87 pop {r2-r3} /* get remainder */ 88 bl .Lnegate_b /* negate it */ 89 pop {r4-r6, pc} 90 91 .align 0 92.Lnegate_a: 93 negs ALO, ALO 94 rsc AHI, AHI, #0 95 mov pc, lr 96 97 .align 0 98.Lnegate_b: 99 negs BLO, BLO 100 rsc BHI, BHI, #0 101 mov pc, lr 102 103 .align 0 104.Lmaxdenom: 105 /* 106 * We had a carry so the denominator must have INT64_MIN 107 * Also BLO and BHI never changed values so we can use 108 * them to see if the numerator has the same value. We 109 * don't have to worry about sign. 110 */ 111 cmp BHI, AHI 112 cmpeq BLO, ALO 113 bne 1f 114 115 /* 116 * They were equal, so we return a quotient of 1 and remainder of 0. 117 */ 118 movs ALO, #1 119 movs AHI, #0 120 movs BLO, #0 121 movs BHI, #0 122 pop {r4-r6, pc} 123 124 /* 125 * Our remainder must be the numerator and our quotient is 0. 126 */ 127 .align 0 1281: movs BLO, ALO 129 movs BHI, AHI 130 movs ALO, #0 131 movs AHI, #0 132 pop {r4-r6, pc} 133END(__aeabi_ldivmod) 134