1c5be3356Smatt/*- 2c5be3356Smatt * Copyright (c) 2012 The NetBSD Foundation, Inc. 3c5be3356Smatt * All rights reserved. 4c5be3356Smatt * 5c5be3356Smatt * This code is derived from software contributed to The NetBSD Foundation 6c5be3356Smatt * by Matt Thomas of 3am Software Foundry. 7c5be3356Smatt * 8c5be3356Smatt * Redistribution and use in source and binary forms, with or without 9c5be3356Smatt * modification, are permitted provided that the following conditions 10c5be3356Smatt * are met: 11c5be3356Smatt * 1. Redistributions of source code must retain the above copyright 12c5be3356Smatt * notice, this list of conditions and the following disclaimer. 13c5be3356Smatt * 2. Redistributions in binary form must reproduce the above copyright 14c5be3356Smatt * notice, this list of conditions and the following disclaimer in the 15c5be3356Smatt * documentation and/or other materials provided with the distribution. 16c5be3356Smatt * 17c5be3356Smatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18c5be3356Smatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19c5be3356Smatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20c5be3356Smatt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21c5be3356Smatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22c5be3356Smatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23c5be3356Smatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24c5be3356Smatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25c5be3356Smatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26c5be3356Smatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27c5be3356Smatt * POSSIBILITY OF SUCH DAMAGE. 28c5be3356Smatt */ 29c5be3356Smatt 30c5be3356Smatt#include <machine/asm.h> 31c5be3356Smatt 32*353aedd8SjoergRCSID("$NetBSD: __aeabi_ldivmod.S,v 1.13 2014/05/06 16:02:11 joerg Exp $") 33c5be3356Smatt 34c5be3356Smatt#ifdef __ARMEB__ 35c5be3356Smatt#define ALO r1 /* incoming numerator, outgoing quotient */ 36c5be3356Smatt#define AHI r0 /* incoming numerator, outgoing quotient */ 37c5be3356Smatt#define BLO r3 /* incoming denominator, outgoing remainder */ 38c5be3356Smatt#define BHI r2 /* incoming denominator, outgoing remainder */ 39c5be3356Smatt#else 40c5be3356Smatt#define ALO r0 /* incoming numerator, outgoing quotient */ 41c5be3356Smatt#define AHI r1 /* incoming numerator, outgoing quotient */ 42c5be3356Smatt#define BLO r2 /* incoming denominator, outgoing remainder */ 43c5be3356Smatt#define BHI r3 /* incoming denominator, outgoing remainder */ 44c5be3356Smatt#endif 45c5be3356Smatt 46eeddcf15SmattENTRY(__aeabi_ldivmod) 47eeddcf15Smatt#ifdef __ARM_EABI__ 48*353aedd8Sjoerg# if !defined(__ARM_DWARF_EH__) 49eeddcf15Smatt .fnstart 50*353aedd8Sjoerg# endif 51eeddcf15Smatt .cfi_startproc 52eeddcf15Smatt#endif 53eeddcf15Smatt#if !defined(_KERNEL) && !defined(_STANDALONE) 54eeddcf15Smatt#if !defined(__thumb__) 55eeddcf15Smatt orrs ip, BLO, BHI 56eeddcf15Smatt beq .Ldivbyzero 57eeddcf15Smatt#elif defined(_ARM_ARCH_T2) 58eeddcf15Smatt cbnz BLO, 1f 59eeddcf15Smatt cbz BHI, .Ldivbyzero 60eeddcf15Smatt#else 61eeddcf15Smatt cmp BLO, #0 62eeddcf15Smatt bne 1f 63eeddcf15Smatt cmp BHI, #0 64eeddcf15Smatt beq .Ldivbyzero 65eeddcf15Smatt#endif 66eeddcf15Smatt1: 67eeddcf15Smatt#endif 68eeddcf15Smatt 69eeddcf15Smatt push {r4-r6, lr} 70eeddcf15Smatt#ifdef __ARM_EABI__ 71eeddcf15Smatt .cfi_def_cfa_offset 16 72eeddcf15Smatt .cfi_offset 14, -4 73eeddcf15Smatt .cfi_offset 6, -8 74eeddcf15Smatt .cfi_offset 5, -12 75eeddcf15Smatt .cfi_offset 4, -16 76eeddcf15Smatt#endif 77eeddcf15Smatt#define NEG r5 78eeddcf15Smatt movs NEG, #0 79eeddcf15Smatt 80c5be3356Smatt cmp BHI, #0 81c5be3356Smatt bge 2f 82eeddcf15Smatt movs NEG, #1 /* flip quotient sign */ 83c5be3356Smatt bl .Lnegate_b 84c5be3356Smatt bcs .Lmaxdenom 85c5be3356Smatt 86c5be3356Smatt2: 87c5be3356Smatt cmp AHI, #0 88eeddcf15Smatt#ifdef __thumb__ 89eeddcf15Smatt bge 3f 90eeddcf15Smatt movs r4, #3 91eeddcf15Smatt eors NEG, NEG, r4 /* flip quotient sign, flip remainder sign */ 92eeddcf15Smatt bl .Lnegate_a 93eeddcf15Smatt3: 94eeddcf15Smatt#else 95c5be3356Smatt eorlt NEG, NEG, #3 /* flip quotient sign, flip remainder sign */ 96c5be3356Smatt bllt .Lnegate_a 97eeddcf15Smatt#endif 98eeddcf15Smatt 99c5be3356Smatt /* 100c5be3356Smatt * Arguments are setup, allocate some stack for the remainder 101c5be3356Smatt * and call __qdivrem for the heavy lifting. 102c5be3356Smatt */ 103eeddcf15Smatt#ifdef __ARM_EABI__ 104eeddcf15Smatt .cfi_def_cfa_offset 32 105eeddcf15Smatt#endif 10604413935Smatt sub sp, sp, #16 107eeddcf15Smatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 108eeddcf15Smatt adds r4, sp, #8 109eeddcf15Smatt#else 110eeddcf15Smatt mov r4, sp 111eeddcf15Smatt adds r4, r4, #8 112eeddcf15Smatt#endif 113eeddcf15Smatt str r4, [sp] 114c5be3356Smatt bl PLT_SYM(__qdivrem) 11504413935Smatt add sp, sp, #8 116eeddcf15Smatt#ifdef __ARM_EABI__ 117eeddcf15Smatt .cfi_def_cfa_offset 24 118eeddcf15Smatt .cfi_offset 3, -20 119eeddcf15Smatt .cfi_offset 2, -24 120eeddcf15Smatt#endif 121c5be3356Smatt 122c5be3356Smatt /* 123c5be3356Smatt * The quotient is already in the right place and neither value 124c5be3356Smatt * needs its sign flipped. 125c5be3356Smatt */ 126eeddcf15Smatt#if defined(__thumb__) && defined(_ARM_ARCH_T2) 127eeddcf15Smatt cbz NEG, .Lnegate_neither 128eeddcf15Smatt#else 129eeddcf15Smatt cmp NEG, #0 /* any signs to flip? */ 130eeddcf15Smatt beq .Lnegate_neither 131eeddcf15Smatt#endif 132c5be3356Smatt 133eeddcf15Smatt cmp NEG, #2 /* does remainder need to be negative? */ 134eeddcf15Smatt beq .Lnegate_b_only /* 2 means b only */ 135eeddcf15Smatt bgt .Lnegate_both /* 3 means both */ 136eeddcf15Smatt.Lnegate_a_only: 137eeddcf15Smatt bl .Lnegate_a /* 1 means a only */ 138eeddcf15Smatt.Lnegate_neither: 139eeddcf15Smatt pop {r2-r6, pc} /* grab b from stack */ 140eeddcf15Smatt.Lnegate_both: 141eeddcf15Smatt bl .Lnegate_a 142eeddcf15Smatt.Lnegate_b_only: 143eeddcf15Smatt pop {r2-r3} /* get remainder */ 144eeddcf15Smatt#ifdef __ARM_EABI__ 145eeddcf15Smatt .cfi_def_cfa_offset 16 146eeddcf15Smatt#endif 147eeddcf15Smatt bl .Lnegate_b /* negate it */ 148eeddcf15Smatt pop {r4-r6, pc} 149c5be3356Smatt 150eeddcf15Smatt .align 0 151c5be3356Smatt.Lnegate_a: 152eeddcf15Smatt#ifdef __thumb__ 153eeddcf15Smatt movs r4, AHI 154eeddcf15Smatt movs AHI, #0 155eeddcf15Smatt negs ALO, ALO 156eeddcf15Smatt sbcs AHI, AHI, r4 157eeddcf15Smatt#else 158eeddcf15Smatt negs ALO, ALO 159c5be3356Smatt rsc AHI, AHI, #0 160eeddcf15Smatt#endif 161c5be3356Smatt RET 162c5be3356Smatt 163eeddcf15Smatt .align 0 164c5be3356Smatt.Lnegate_b: 165eeddcf15Smatt#ifdef __thumb__ 166eeddcf15Smatt movs r4, BHI 167eeddcf15Smatt movs BHI, #0 168eeddcf15Smatt negs BLO, BLO 169eeddcf15Smatt sbcs BHI, BHI, r4 170eeddcf15Smatt#else 171eeddcf15Smatt negs BLO, BLO 172c5be3356Smatt rsc BHI, BHI, #0 173eeddcf15Smatt#endif 174c5be3356Smatt RET 175c5be3356Smatt 176eeddcf15Smatt .align 0 177c5be3356Smatt.Lmaxdenom: 178c5be3356Smatt /* 179c5be3356Smatt * We had a carry so the denominator must have INT64_MIN 180c5be3356Smatt * Also BLO and BHI never changed values so we can use 181c5be3356Smatt * them to see if the numerator has the same value. We 182c5be3356Smatt * don't have to worry about sign. 183c5be3356Smatt */ 184eeddcf15Smatt cmp BHI, AHI 185eeddcf15Smatt#ifdef __thumb__ 186eeddcf15Smatt bne 1f 187eeddcf15Smatt cmp BLO, ALO 188eeddcf15Smatt#else 189eeddcf15Smatt cmpeq BLO, ALO 190eeddcf15Smatt#endif 191c5be3356Smatt bne 1f 192c5be3356Smatt 193c5be3356Smatt /* 194c5be3356Smatt * They were equal, so we return a quotient of 1 and remainder of 0. 195c5be3356Smatt */ 196eeddcf15Smatt movs ALO, #1 197eeddcf15Smatt movs AHI, #0 198eeddcf15Smatt movs BLO, #0 199eeddcf15Smatt movs BHI, #0 200eeddcf15Smatt pop {r4-r6, pc} 201c5be3356Smatt 202c5be3356Smatt /* 203c5be3356Smatt * Our remainder must be the numerator and our quotient is 0. 204c5be3356Smatt */ 205eeddcf15Smatt .align 0 206eeddcf15Smatt1: movs BLO, ALO 207eeddcf15Smatt movs BHI, AHI 208eeddcf15Smatt movs ALO, #0 209eeddcf15Smatt movs AHI, #0 210eeddcf15Smatt pop {r4-r6, pc} 2118ef5fb1fSmatt 212d1e50f81Smatt#if !defined(_KERNEL) && !defined(_STANDALONE) 213eeddcf15Smatt .align 0 2148ef5fb1fSmatt.Ldivbyzero: 215eeddcf15Smatt push {r0-r1,r4,lr} 216eeddcf15Smatt#ifdef __ARM_EABI__ 217*353aedd8Sjoerg# if !defined(__ARM_DWARF_EH__) 218eeddcf15Smatt .save {r0-r1,r4,lr} 219*353aedd8Sjoerg# endif 220eeddcf15Smatt .cfi_def_cfa_offset 16 221eeddcf15Smatt .cfi_offset 14, -4 222eeddcf15Smatt .cfi_offset 4, -8 223eeddcf15Smatt#endif 2246fec0397Sskrll cmp AHI, #0 225eeddcf15Smatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 226eeddcf15Smatt#ifdef __thumb__ 227eeddcf15Smatt ittee ge 228eeddcf15Smatt#endif 2298ef5fb1fSmatt mvnge ALO, #0 230eeddcf15Smatt mvnge AHI, #0x80000000 2318ef5fb1fSmatt movlt ALO, #0 2321271d298Smatt movlt AHI, #0x80000000 233eeddcf15Smatt#else 234eeddcf15Smatt blt 1f 235eeddcf15Smatt movs ALO, #0 236eeddcf15Smatt mvns ALO, ALO 237eeddcf15Smatt mov AHI, ALO 238eeddcf15Smatt lsrs AHI, AHI, #1 239eeddcf15Smatt b 2f 240eeddcf15Smatt1: 241eeddcf15Smatt movs ALO, #0 242eeddcf15Smatt movs AHI, #1 243eeddcf15Smatt lsls AHI, AHI, #31 244eeddcf15Smatt2: 245eeddcf15Smatt#endif /* __thumb__ && !_ARM_ARCH_T2 */ 2468ef5fb1fSmatt bl PLT_SYM(__aeabi_ldiv0) 247eeddcf15Smatt pop {r2-r4, pc} 248eeddcf15Smatt#endif /* !_KERNEL && !_STANDALONE */ 249eeddcf15Smatt#ifdef __ARM_EABI__ 250eeddcf15Smatt .cfi_endproc 251*353aedd8Sjoerg# if !defined(__ARM_DWARF_EH__) 252eeddcf15Smatt .fnend 253d1e50f81Smatt# endif 254*353aedd8Sjoerg#endif 255c5be3356SmattEND(__aeabi_ldivmod) 256