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