1/* 2 * Copyright (c) 2014 ARM Ltd 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the company may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* An executable stack is *not* required for these functions. */ 30 31.section .note.GNU-stack,"",%progbits 32.previous 33.eabi_attribute 25, 1 34 35/* ANSI concatenation macros. */ 36 37#define CONCAT1(a, b) CONCAT2(a, b) 38#define CONCAT2(a, b) a ## b 39 40/* Use the right prefix for global labels. */ 41 42#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) 43 44#define TYPE(x) .type SYM(x),function 45#define SIZE(x) .size SYM(x), . - SYM(x) 46#define LSYM(x) .x 47 48.macro cfi_start start_label, end_label 49 .pushsection .debug_frame 50LSYM(Lstart_frame): 51 .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) 52LSYM(Lstart_cie): 53 .4byte 0xffffffff 54 .byte 0x1 55 .ascii "\0" 56 .uleb128 0x1 57 .sleb128 -4 58 .byte 0xe 59 .byte 0xc 60 .uleb128 0xd 61 .uleb128 0x0 62 63 .align 2 64LSYM(Lend_cie): 65 .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) 66LSYM(Lstart_fde): 67 .4byte LSYM(Lstart_frame) 68 .4byte \start_label 69 .4byte \end_label-\start_label 70 .popsection 71.endm 72 73.macro cfi_end end_label 74 .pushsection .debug_frame 75 .align 2 76LSYM(Lend_fde): 77 .popsection 78\end_label: 79.endm 80 81.macro THUMB_LDIV0 name signed 82 push {r0, lr} 83 movs r0, #0 84 bl SYM(__aeabi_idiv0) 85 pop {r1, pc} 86.endm 87 88.macro FUNC_END name 89 SIZE (__\name) 90.endm 91 92.macro DIV_FUNC_END name signed 93 cfi_start __\name, LSYM(Lend_div0) 94LSYM(Ldiv0): 95 THUMB_LDIV0 \name \signed 96 cfi_end LSYM(Lend_div0) 97 FUNC_END \name 98.endm 99 100.macro THUMB_FUNC_START name 101 .globl SYM (\name) 102 TYPE (\name) 103 .thumb_func 104SYM (\name): 105.endm 106 107.macro FUNC_START name 108 .text 109 .globl SYM (__\name) 110 TYPE (__\name) 111 .align 0 112 .force_thumb 113 .thumb_func 114 .syntax unified 115SYM (__\name): 116.endm 117 118.macro FUNC_ALIAS new old 119 .globl SYM (__\new) 120 .thumb_set SYM (__\new), SYM (__\old) 121.endm 122 123/* Register aliases. */ 124work .req r4 125dividend .req r0 126divisor .req r1 127overdone .req r2 128result .req r2 129curbit .req r3 130 131/* ------------------------------------------------------------------------ */ 132/* Bodies of the division and modulo routines. */ 133/* ------------------------------------------------------------------------ */ 134.macro BranchToDiv n, label 135 lsrs curbit, dividend, \n 136 cmp curbit, divisor 137 bcc \label 138.endm 139 140.macro DoDiv n 141 lsrs curbit, dividend, \n 142 cmp curbit, divisor 143 bcc 1f 144 lsls curbit, divisor, \n 145 subs dividend, dividend, curbit 146 1471: adcs result, result 148.endm 149 150.macro THUMB1_Div_Positive 151 movs result, #0 152 BranchToDiv #1, LSYM(Lthumb1_div1) 153 BranchToDiv #4, LSYM(Lthumb1_div4) 154 BranchToDiv #8, LSYM(Lthumb1_div8) 155 BranchToDiv #12, LSYM(Lthumb1_div12) 156 BranchToDiv #16, LSYM(Lthumb1_div16) 157LSYM(Lthumb1_div_large_positive): 158 movs result, #0xff 159 lsls divisor, divisor, #8 160 rev result, result 161 lsrs curbit, dividend, #16 162 cmp curbit, divisor 163 bcc 1f 164 asrs result, #8 165 lsls divisor, divisor, #8 166 beq LSYM(Ldivbyzero_waypoint) 167 1681: lsrs curbit, dividend, #12 169 cmp curbit, divisor 170 bcc LSYM(Lthumb1_div12) 171 b LSYM(Lthumb1_div16) 172LSYM(Lthumb1_div_loop): 173 lsrs divisor, divisor, #8 174LSYM(Lthumb1_div16): 175 Dodiv #15 176 Dodiv #14 177 Dodiv #13 178 Dodiv #12 179LSYM(Lthumb1_div12): 180 Dodiv #11 181 Dodiv #10 182 Dodiv #9 183 Dodiv #8 184 bcs LSYM(Lthumb1_div_loop) 185LSYM(Lthumb1_div8): 186 Dodiv #7 187 Dodiv #6 188 Dodiv #5 189LSYM(Lthumb1_div5): 190 Dodiv #4 191LSYM(Lthumb1_div4): 192 Dodiv #3 193LSYM(Lthumb1_div3): 194 Dodiv #2 195LSYM(Lthumb1_div2): 196 Dodiv #1 197LSYM(Lthumb1_div1): 198 subs divisor, dividend, divisor 199 bcs 1f 200 mov divisor, dividend 201 2021: adcs result, result 203 mov dividend, result 204 bx lr 205 206LSYM(Ldivbyzero_waypoint): 207 b LSYM(Ldiv0) 208.endm 209 210.macro THUMB1_Div_Negative 211 lsrs result, divisor, #31 212 beq 1f 213 rsbs divisor, divisor, #0 214 2151: asrs curbit, dividend, #32 216 bcc 2f 217 rsbs dividend, dividend, #0 218 2192: eors curbit, result 220 movs result, #0 221 mov ip, curbit 222 BranchToDiv #4, LSYM(Lthumb1_div_negative4) 223 BranchToDiv #8, LSYM(Lthumb1_div_negative8) 224LSYM(Lthumb1_div_large): 225 movs result, #0xfc 226 lsls divisor, divisor, #6 227 rev result, result 228 lsrs curbit, dividend, #8 229 cmp curbit, divisor 230 bcc LSYM(Lthumb1_div_negative8) 231 232 lsls divisor, divisor, #6 233 asrs result, result, #6 234 cmp curbit, divisor 235 bcc LSYM(Lthumb1_div_negative8) 236 237 lsls divisor, divisor, #6 238 asrs result, result, #6 239 cmp curbit, divisor 240 bcc LSYM(Lthumb1_div_negative8) 241 242 lsls divisor, divisor, #6 243 beq LSYM(Ldivbyzero_negative) 244 asrs result, result, #6 245 b LSYM(Lthumb1_div_negative8) 246LSYM(Lthumb1_div_negative_loop): 247 lsrs divisor, divisor, #6 248LSYM(Lthumb1_div_negative8): 249 DoDiv #7 250 DoDiv #6 251 DoDiv #5 252 DoDiv #4 253LSYM(Lthumb1_div_negative4): 254 DoDiv #3 255 DoDiv #2 256 bcs LSYM(Lthumb1_div_negative_loop) 257 DoDiv #1 258 subs divisor, dividend, divisor 259 bcs 1f 260 mov divisor, dividend 261 2621: mov curbit, ip 263 adcs result, result 264 asrs curbit, curbit, #1 265 mov dividend, result 266 bcc 2f 267 rsbs dividend, dividend, #0 268 cmp curbit, #0 269 2702: bpl 3f 271 rsbs divisor, divisor, #0 272 2733: bx lr 274 275LSYM(Ldivbyzero_negative): 276 mov curbit, ip 277 asrs curbit, curbit, #1 278 bcc LSYM(Ldiv0) 279 rsbs dividend, dividend, #0 280.endm 281 282/* ------------------------------------------------------------------------ */ 283/* Start of the Real Functions */ 284/* ------------------------------------------------------------------------ */ 285 286 FUNC_START aeabi_idiv0 287 bx lr 288 FUNC_END aeabi_idiv0 289 290 FUNC_START divsi3 291 FUNC_ALIAS aeabi_idiv divsi3 292 293LSYM(divsi3_skip_div0_test): 294 mov curbit, dividend 295 orrs curbit, divisor 296 bmi LSYM(Lthumb1_div_negative) 297 298LSYM(Lthumb1_div_positive): 299 THUMB1_Div_Positive 300 301LSYM(Lthumb1_div_negative): 302 THUMB1_Div_Negative 303 304 DIV_FUNC_END divsi3 signed 305 306 FUNC_START aeabi_idivmod 307 308 cmp r1, #0 309 beq LSYM(Ldiv0) 310 push {r0, r1, lr} 311 bl LSYM(divsi3_skip_div0_test) 312 POP {r1, r2, r3} 313 mul r2, r0 314 sub r1, r1, r2 315 bx r3 316 317 FUNC_END aeabi_idivmod 318/* ------------------------------------------------------------------------ */ 319