1210284Sjmallett/*- 2232812Sjmallett * Copyright (c) 2012 The NetBSD Foundation, Inc. 3215990Sjmallett * All rights reserved. 4210284Sjmallett * 5210284Sjmallett * This code is derived from software contributed to The NetBSD Foundation 6215990Sjmallett * by Matt Thomas of 3am Software Foundry. 7215990Sjmallett * 8215990Sjmallett * Redistribution and use in source and binary forms, with or without 9210284Sjmallett * modification, are permitted provided that the following conditions 10215990Sjmallett * are met: 11215990Sjmallett * 1. Redistributions of source code must retain the above copyright 12210284Sjmallett * notice, this list of conditions and the following disclaimer. 13215990Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 14215990Sjmallett * notice, this list of conditions and the following disclaimer in the 15215990Sjmallett * documentation and/or other materials provided with the distribution. 16215990Sjmallett * 17215990Sjmallett * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18232812Sjmallett * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19215990Sjmallett * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20215990Sjmallett * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21215990Sjmallett * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22215990Sjmallett * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23215990Sjmallett * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24215990Sjmallett * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25215990Sjmallett * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26215990Sjmallett * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27215990Sjmallett * POSSIBILITY OF SUCH DAMAGE. 28215990Sjmallett */ 29232812Sjmallett 30215990Sjmallett#include <machine/asm.h> 31215990Sjmallett 32215990SjmallettRCSID("$NetBSD: __aeabi_ldivmod.S,v 1.12 2013/08/19 03:27:34 matt Exp $") 33215990Sjmallett 34215990Sjmallett#ifdef __ARMEB__ 35215990Sjmallett#define ALO r1 /* incoming numerator, outgoing quotient */ 36215990Sjmallett#define AHI r0 /* incoming numerator, outgoing quotient */ 37215990Sjmallett#define BLO r3 /* incoming denominator, outgoing remainder */ 38210284Sjmallett#define BHI r2 /* incoming denominator, outgoing remainder */ 39210284Sjmallett#else 40210284Sjmallett#define ALO r0 /* incoming numerator, outgoing quotient */ 41210284Sjmallett#define AHI r1 /* incoming numerator, outgoing quotient */ 42210284Sjmallett#define BLO r2 /* incoming denominator, outgoing remainder */ 43210284Sjmallett#define BHI r3 /* incoming denominator, outgoing remainder */ 44215990Sjmallett#endif 45210284Sjmallett 46210284SjmallettENTRY(__aeabi_ldivmod) 47210284Sjmallett#ifdef __ARM_EABI__ 48210284Sjmallett# if !defined(__ARM_DWARF_EH__) 49232812Sjmallett .fnstart 50210284Sjmallett# endif 51210284Sjmallett .cfi_startproc 52210284Sjmallett#endif 53210284Sjmallett#if !defined(_KERNEL) && !defined(_STANDALONE) 54210284Sjmallett#if !defined(__thumb__) 55210284Sjmallett orrs ip, BLO, BHI 56210284Sjmallett beq .Ldivbyzero 57210284Sjmallett#elif defined(_ARM_ARCH_T2) 58210284Sjmallett cbnz BLO, 1f 59210284Sjmallett cbz BHI, .Ldivbyzero 60210284Sjmallett#else 61210284Sjmallett cmp BLO, #0 62210284Sjmallett bne 1f 63210284Sjmallett cmp BHI, #0 64210284Sjmallett beq .Ldivbyzero 65232812Sjmallett#endif 66210284Sjmallett1: 67210284Sjmallett#endif 68210284Sjmallett 69210284Sjmallett push {r4-r6, lr} 70210284Sjmallett#ifdef __ARM_EABI__ 71210284Sjmallett .cfi_def_cfa_offset 16 72210284Sjmallett .cfi_offset 14, -4 73210284Sjmallett .cfi_offset 6, -8 74210284Sjmallett .cfi_offset 5, -12 75210284Sjmallett .cfi_offset 4, -16 76210284Sjmallett#endif 77210284Sjmallett#define NEG r5 78215990Sjmallett movs NEG, #0 79232812Sjmallett 80210284Sjmallett cmp BHI, #0 81210284Sjmallett bge 2f 82210284Sjmallett movs NEG, #1 /* flip quotient sign */ 83210284Sjmallett bl .Lnegate_b 84210284Sjmallett bcs .Lmaxdenom 85210284Sjmallett 86210284Sjmallett2: 87210284Sjmallett cmp AHI, #0 88210284Sjmallett#ifdef __thumb__ 89210284Sjmallett bge 3f 90210284Sjmallett movs r4, #3 91210284Sjmallett eors NEG, NEG, r4 /* flip quotient sign, flip remainder sign */ 92210284Sjmallett bl .Lnegate_a 93210284Sjmallett3: 94210284Sjmallett#else 95210284Sjmallett eorlt NEG, NEG, #3 /* flip quotient sign, flip remainder sign */ 96210284Sjmallett bllt .Lnegate_a 97210284Sjmallett#endif 98210284Sjmallett 99210284Sjmallett /* 100210284Sjmallett * Arguments are setup, allocate some stack for the remainder 101210284Sjmallett * and call __qdivrem for the heavy lifting. 102210284Sjmallett */ 103210284Sjmallett#ifdef __ARM_EABI__ 104210284Sjmallett .cfi_def_cfa_offset 32 105210284Sjmallett#endif 106210284Sjmallett sub sp, sp, #16 107210284Sjmallett#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 108210284Sjmallett adds r4, sp, #8 109210284Sjmallett#else 110210284Sjmallett mov r4, sp 111210284Sjmallett adds r4, r4, #8 112210284Sjmallett#endif 113210284Sjmallett str r4, [sp] 114210284Sjmallett bl PLT_SYM(__qdivrem) 115210284Sjmallett add sp, sp, #8 116210284Sjmallett#ifdef __ARM_EABI__ 117210284Sjmallett .cfi_def_cfa_offset 24 118210284Sjmallett .cfi_offset 3, -20 119210284Sjmallett .cfi_offset 2, -24 120210284Sjmallett#endif 121210284Sjmallett 122210284Sjmallett /* 123250428Simp * The quotient is already in the right place and neither value 124250428Simp * needs its sign flipped. 125210284Sjmallett */ 126250428Simp#if defined(__thumb__) && defined(_ARM_ARCH_T2) 127232812Sjmallett cbz NEG, .Lnegate_neither 128232812Sjmallett#else 129232812Sjmallett cmp NEG, #0 /* any signs to flip? */ 130232812Sjmallett beq .Lnegate_neither 131232812Sjmallett#endif 132232812Sjmallett 133232812Sjmallett cmp NEG, #2 /* does remainder need to be negative? */ 134232812Sjmallett beq .Lnegate_b_only /* 2 means b only */ 135232812Sjmallett bgt .Lnegate_both /* 3 means both */ 136232812Sjmallett.Lnegate_a_only: 137232812Sjmallett bl .Lnegate_a /* 1 means a only */ 138210284Sjmallett.Lnegate_neither: 139232812Sjmallett pop {r2-r6, pc} /* grab b from stack */ 140232812Sjmallett.Lnegate_both: 141232812Sjmallett bl .Lnegate_a 142232812Sjmallett.Lnegate_b_only: 143210284Sjmallett pop {r2-r3} /* get remainder */ 144232812Sjmallett#ifdef __ARM_EABI__ 145232812Sjmallett .cfi_def_cfa_offset 16 146232812Sjmallett#endif 147232812Sjmallett bl .Lnegate_b /* negate it */ 148232812Sjmallett pop {r4-r6, pc} 149232812Sjmallett 150232812Sjmallett .align 0 151232812Sjmallett.Lnegate_a: 152232812Sjmallett#ifdef __thumb__ 153232812Sjmallett movs r4, AHI 154232812Sjmallett movs AHI, #0 155232812Sjmallett negs ALO, ALO 156232812Sjmallett sbcs AHI, AHI, r4 157232812Sjmallett#else 158232812Sjmallett negs ALO, ALO 159232812Sjmallett rsc AHI, AHI, #0 160232812Sjmallett#endif 161232812Sjmallett RET 162232812Sjmallett 163232812Sjmallett .align 0 164232812Sjmallett.Lnegate_b: 165232812Sjmallett#ifdef __thumb__ 166232812Sjmallett movs r4, BHI 167232812Sjmallett movs BHI, #0 168232812Sjmallett negs BLO, BLO 169232812Sjmallett sbcs BHI, BHI, r4 170232812Sjmallett#else 171232812Sjmallett negs BLO, BLO 172232812Sjmallett rsc BHI, BHI, #0 173232812Sjmallett#endif 174232812Sjmallett RET 175232812Sjmallett 176232812Sjmallett .align 0 177232812Sjmallett.Lmaxdenom: 178232812Sjmallett /* 179232812Sjmallett * We had a carry so the denominator must have INT64_MIN 180232812Sjmallett * Also BLO and BHI never changed values so we can use 181232812Sjmallett * them to see if the numerator has the same value. We 182232812Sjmallett * don't have to worry about sign. 183232812Sjmallett */ 184232812Sjmallett cmp BHI, AHI 185232812Sjmallett#ifdef __thumb__ 186232812Sjmallett bne 1f 187232812Sjmallett cmp BLO, ALO 188232812Sjmallett#else 189232812Sjmallett cmpeq BLO, ALO 190232812Sjmallett#endif 191215990Sjmallett bne 1f 192210284Sjmallett 193215990Sjmallett /* 194215990Sjmallett * They were equal, so we return a quotient of 1 and remainder of 0. 195210284Sjmallett */ 196210284Sjmallett movs ALO, #1 197210284Sjmallett movs AHI, #0 198210284Sjmallett movs BLO, #0 199210284Sjmallett movs BHI, #0 200210284Sjmallett pop {r4-r6, pc} 201210284Sjmallett 202210284Sjmallett /* 203210284Sjmallett * Our remainder must be the numerator and our quotient is 0. 204210284Sjmallett */ 205210284Sjmallett .align 0 206210284Sjmallett1: movs BLO, ALO 207210284Sjmallett movs BHI, AHI 208210284Sjmallett movs ALO, #0 209210284Sjmallett movs AHI, #0 210210284Sjmallett pop {r4-r6, pc} 211210284Sjmallett 212210284Sjmallett#if !defined(_KERNEL) && !defined(_STANDALONE) 213210284Sjmallett .align 0 214232812Sjmallett.Ldivbyzero: 215210284Sjmallett push {r0-r1,r4,lr} 216210284Sjmallett#ifdef __ARM_EABI__ 217210284Sjmallett# if !defined(__ARM_DWARF_EH__) 218210284Sjmallett .save {r0-r1,r4,lr} 219210284Sjmallett# endif 220210284Sjmallett .cfi_def_cfa_offset 16 221210284Sjmallett .cfi_offset 14, -4 222250428Simp .cfi_offset 4, -8 223250428Simp#endif 224250428Simp cmp AHI, #0 225250428Simp#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 226250428Simp#ifdef __thumb__ 227250428Simp ittee ge 228210284Sjmallett#endif 229210284Sjmallett mvnge ALO, #0 230210284Sjmallett mvnge AHI, #0x80000000 231210284Sjmallett movlt ALO, #0 232250428Simp movlt AHI, #0x80000000 233210284Sjmallett#else 234210284Sjmallett blt 1f 235210284Sjmallett movs ALO, #0 236210284Sjmallett mvns ALO, ALO 237210284Sjmallett mov AHI, ALO 238210284Sjmallett lsrs AHI, AHI, #1 239210284Sjmallett b 2f 240210284Sjmallett1: 241210284Sjmallett movs ALO, #0 242210284Sjmallett movs AHI, #1 243210284Sjmallett lsls AHI, AHI, #31 244210284Sjmallett2: 245215990Sjmallett#endif /* __thumb__ && !_ARM_ARCH_T2 */ 246215990Sjmallett bl PLT_SYM(__aeabi_ldiv0) 247215990Sjmallett pop {r2-r4, pc} 248215990Sjmallett#endif /* !_KERNEL && !_STANDALONE */ 249215990Sjmallett#ifdef __ARM_EABI__ 250215990Sjmallett .cfi_endproc 251215990Sjmallett# if !defined(__ARM_DWARF_EH__) 252215990Sjmallett .fnend 253215990Sjmallett# endif 254232812Sjmallett#endif 255232812SjmallettEND(__aeabi_ldivmod) 256232812Sjmallett