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