1132718Skan/* ieee754-df.S double-precision floating point support for ARM 2132718Skan 3169689Skan Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. 4132718Skan Contributed by Nicolas Pitre (nico@cam.org) 5132718Skan 6132718Skan This file is free software; you can redistribute it and/or modify it 7132718Skan under the terms of the GNU General Public License as published by the 8132718Skan Free Software Foundation; either version 2, or (at your option) any 9132718Skan later version. 10132718Skan 11132718Skan In addition to the permissions in the GNU General Public License, the 12132718Skan Free Software Foundation gives you unlimited permission to link the 13132718Skan compiled version of this file into combinations with other programs, 14132718Skan and to distribute those combinations without any restriction coming 15132718Skan from the use of this file. (The General Public License restrictions 16132718Skan do apply in other respects; for example, they cover modification of 17132718Skan the file, and distribution when not linked into a combine 18132718Skan executable.) 19132718Skan 20132718Skan This file is distributed in the hope that it will be useful, but 21132718Skan WITHOUT ANY WARRANTY; without even the implied warranty of 22132718Skan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23132718Skan General Public License for more details. 24132718Skan 25132718Skan You should have received a copy of the GNU General Public License 26132718Skan along with this program; see the file COPYING. If not, write to 27169689Skan the Free Software Foundation, 51 Franklin Street, Fifth Floor, 28169689Skan Boston, MA 02110-1301, USA. */ 29132718Skan 30132718Skan/* 31132718Skan * Notes: 32132718Skan * 33132718Skan * The goal of this code is to be as fast as possible. This is 34132718Skan * not meant to be easy to understand for the casual reader. 35132718Skan * For slightly simpler code please see the single precision version 36132718Skan * of this file. 37132718Skan * 38132718Skan * Only the default rounding mode is intended for best performances. 39132718Skan * Exceptions aren't supported yet, but that can be added quite easily 40132718Skan * if necessary without impacting performances. 41132718Skan */ 42132718Skan 43132718Skan 44132718Skan@ For FPA, float words are always big-endian. 45132718Skan@ For VFP, floats words follow the memory system mode. 46132718Skan#if defined(__VFP_FP__) && !defined(__ARMEB__) 47132718Skan#define xl r0 48132718Skan#define xh r1 49132718Skan#define yl r2 50132718Skan#define yh r3 51132718Skan#else 52132718Skan#define xh r0 53132718Skan#define xl r1 54132718Skan#define yh r2 55132718Skan#define yl r3 56132718Skan#endif 57132718Skan 58132718Skan 59132718Skan#ifdef L_negdf2 60132718Skan 61132718SkanARM_FUNC_START negdf2 62169689SkanARM_FUNC_ALIAS aeabi_dneg negdf2 63169689Skan 64132718Skan @ flip sign bit 65132718Skan eor xh, xh, #0x80000000 66132718Skan RET 67132718Skan 68169689Skan FUNC_END aeabi_dneg 69132718Skan FUNC_END negdf2 70132718Skan 71132718Skan#endif 72132718Skan 73132718Skan#ifdef L_addsubdf3 74132718Skan 75169689SkanARM_FUNC_START aeabi_drsub 76169689Skan 77169689Skan eor xh, xh, #0x80000000 @ flip sign bit of first arg 78169689Skan b 1f 79169689Skan 80132718SkanARM_FUNC_START subdf3 81169689SkanARM_FUNC_ALIAS aeabi_dsub subdf3 82169689Skan 83169689Skan eor yh, yh, #0x80000000 @ flip sign bit of second arg 84169689Skan#if defined(__INTERWORKING_STUBS__) 85132718Skan b 1f @ Skip Thumb-code prologue 86132718Skan#endif 87132718Skan 88132718SkanARM_FUNC_START adddf3 89169689SkanARM_FUNC_ALIAS aeabi_dadd adddf3 90132718Skan 91169689Skan1: stmfd sp!, {r4, r5, lr} 92132718Skan 93169689Skan @ Look for zeroes, equal values, INF, or NAN. 94169689Skan mov r4, xh, lsl #1 95169689Skan mov r5, yh, lsl #1 96169689Skan teq r4, r5 97169689Skan teqeq xl, yl 98169689Skan orrnes ip, r4, xl 99169689Skan orrnes ip, r5, yl 100169689Skan mvnnes ip, r4, asr #21 101169689Skan mvnnes ip, r5, asr #21 102169689Skan beq LSYM(Lad_s) 103132718Skan 104132718Skan @ Compute exponent difference. Make largest exponent in r4, 105132718Skan @ corresponding arg in xh-xl, and positive exponent difference in r5. 106169689Skan mov r4, r4, lsr #21 107169689Skan rsbs r5, r4, r5, lsr #21 108132718Skan rsblt r5, r5, #0 109132718Skan ble 1f 110132718Skan add r4, r4, r5 111132718Skan eor yl, xl, yl 112132718Skan eor yh, xh, yh 113132718Skan eor xl, yl, xl 114132718Skan eor xh, yh, xh 115132718Skan eor yl, xl, yl 116132718Skan eor yh, xh, yh 117132718Skan1: 118132718Skan @ If exponent difference is too large, return largest argument 119132718Skan @ already in xh-xl. We need up to 54 bit to handle proper rounding 120132718Skan @ of 0x1p54 - 1.1. 121169689Skan cmp r5, #54 122132718Skan RETLDM "r4, r5" hi 123132718Skan 124132718Skan @ Convert mantissa to signed integer. 125132718Skan tst xh, #0x80000000 126169689Skan mov xh, xh, lsl #12 127169689Skan mov ip, #0x00100000 128169689Skan orr xh, ip, xh, lsr #12 129132718Skan beq 1f 130132718Skan rsbs xl, xl, #0 131132718Skan rsc xh, xh, #0 132132718Skan1: 133132718Skan tst yh, #0x80000000 134169689Skan mov yh, yh, lsl #12 135169689Skan orr yh, ip, yh, lsr #12 136132718Skan beq 1f 137132718Skan rsbs yl, yl, #0 138132718Skan rsc yh, yh, #0 139132718Skan1: 140132718Skan @ If exponent == difference, one or both args were denormalized. 141132718Skan @ Since this is not common case, rescale them off line. 142132718Skan teq r4, r5 143132718Skan beq LSYM(Lad_d) 144132718SkanLSYM(Lad_x): 145132718Skan 146169689Skan @ Compensate for the exponent overlapping the mantissa MSB added later 147169689Skan sub r4, r4, #1 148169689Skan 149169689Skan @ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip. 150169689Skan rsbs lr, r5, #32 151169689Skan blt 1f 152132718Skan mov ip, yl, lsl lr 153169689Skan adds xl, xl, yl, lsr r5 154169689Skan adc xh, xh, #0 155169689Skan adds xl, xl, yh, lsl lr 156169689Skan adcs xh, xh, yh, asr r5 157169689Skan b 2f 158169689Skan1: sub r5, r5, #32 159132718Skan add lr, lr, #32 160132718Skan cmp yl, #1 161169689Skan mov ip, yh, lsl lr 162169689Skan orrcs ip, ip, #2 @ 2 not 1, to allow lsr #1 later 163169689Skan adds xl, xl, yh, asr r5 164169689Skan adcs xh, xh, yh, asr #31 165169689Skan2: 166132718Skan @ We now have a result in xh-xl-ip. 167169689Skan @ Keep absolute value in xh-xl-ip, sign in r5 (the n bit was set above) 168169689Skan and r5, xh, #0x80000000 169132718Skan bpl LSYM(Lad_p) 170132718Skan rsbs ip, ip, #0 171132718Skan rscs xl, xl, #0 172132718Skan rsc xh, xh, #0 173132718Skan 174132718Skan @ Determine how to normalize the result. 175132718SkanLSYM(Lad_p): 176132718Skan cmp xh, #0x00100000 177169689Skan bcc LSYM(Lad_a) 178132718Skan cmp xh, #0x00200000 179169689Skan bcc LSYM(Lad_e) 180132718Skan 181132718Skan @ Result needs to be shifted right. 182132718Skan movs xh, xh, lsr #1 183132718Skan movs xl, xl, rrx 184169689Skan mov ip, ip, rrx 185169689Skan add r4, r4, #1 186132718Skan 187169689Skan @ Make sure we did not bust our exponent. 188169689Skan mov r2, r4, lsl #21 189169689Skan cmn r2, #(2 << 21) 190169689Skan bcs LSYM(Lad_o) 191169689Skan 192132718Skan @ Our result is now properly aligned into xh-xl, remaining bits in ip. 193132718Skan @ Round with MSB of ip. If halfway between two numbers, round towards 194132718Skan @ LSB of xl = 0. 195132718Skan @ Pack final result together. 196132718SkanLSYM(Lad_e): 197169689Skan cmp ip, #0x80000000 198169689Skan moveqs ip, xl, lsr #1 199169689Skan adcs xl, xl, #0 200169689Skan adc xh, xh, r4, lsl #20 201132718Skan orr xh, xh, r5 202132718Skan RETLDM "r4, r5" 203132718Skan 204169689Skan @ Result must be shifted left and exponent adjusted. 205169689SkanLSYM(Lad_a): 206169689Skan movs ip, ip, lsl #1 207169689Skan adcs xl, xl, xl 208169689Skan adc xh, xh, xh 209169689Skan tst xh, #0x00100000 210169689Skan sub r4, r4, #1 211169689Skan bne LSYM(Lad_e) 212169689Skan 213169689Skan @ No rounding necessary since ip will always be 0 at this point. 214132718SkanLSYM(Lad_l): 215169689Skan 216132718Skan#if __ARM_ARCH__ < 5 217132718Skan 218132718Skan teq xh, #0 219169689Skan movne r3, #20 220169689Skan moveq r3, #52 221132718Skan moveq xh, xl 222132718Skan moveq xl, #0 223132718Skan mov r2, xh 224169689Skan cmp r2, #(1 << 16) 225169689Skan movhs r2, r2, lsr #16 226169689Skan subhs r3, r3, #16 227169689Skan cmp r2, #(1 << 8) 228169689Skan movhs r2, r2, lsr #8 229169689Skan subhs r3, r3, #8 230169689Skan cmp r2, #(1 << 4) 231169689Skan movhs r2, r2, lsr #4 232169689Skan subhs r3, r3, #4 233169689Skan cmp r2, #(1 << 2) 234169689Skan subhs r3, r3, #2 235169689Skan sublo r3, r3, r2, lsr #1 236169689Skan sub r3, r3, r2, lsr #3 237132718Skan 238132718Skan#else 239132718Skan 240132718Skan teq xh, #0 241132718Skan moveq xh, xl 242132718Skan moveq xl, #0 243132718Skan clz r3, xh 244132718Skan addeq r3, r3, #32 245132718Skan sub r3, r3, #11 246132718Skan 247132718Skan#endif 248132718Skan 249132718Skan @ determine how to shift the value. 250132718Skan subs r2, r3, #32 251132718Skan bge 2f 252132718Skan adds r2, r2, #12 253132718Skan ble 1f 254132718Skan 255132718Skan @ shift value left 21 to 31 bits, or actually right 11 to 1 bits 256132718Skan @ since a register switch happened above. 257132718Skan add ip, r2, #20 258132718Skan rsb r2, r2, #12 259132718Skan mov xl, xh, lsl ip 260132718Skan mov xh, xh, lsr r2 261132718Skan b 3f 262132718Skan 263132718Skan @ actually shift value left 1 to 20 bits, which might also represent 264132718Skan @ 32 to 52 bits if counting the register switch that happened earlier. 265132718Skan1: add r2, r2, #20 266132718Skan2: rsble ip, r2, #32 267132718Skan mov xh, xh, lsl r2 268132718Skan orrle xh, xh, xl, lsr ip 269132718Skan movle xl, xl, lsl r2 270132718Skan 271132718Skan @ adjust exponent accordingly. 272169689Skan3: subs r4, r4, r3 273169689Skan addge xh, xh, r4, lsl #20 274169689Skan orrge xh, xh, r5 275169689Skan RETLDM "r4, r5" ge 276132718Skan 277132718Skan @ Exponent too small, denormalize result. 278132718Skan @ Find out proper shift value. 279169689Skan mvn r4, r4 280169689Skan subs r4, r4, #31 281132718Skan bge 2f 282132718Skan adds r4, r4, #12 283132718Skan bgt 1f 284132718Skan 285132718Skan @ shift result right of 1 to 20 bits, sign is in r5. 286132718Skan add r4, r4, #20 287132718Skan rsb r2, r4, #32 288132718Skan mov xl, xl, lsr r4 289132718Skan orr xl, xl, xh, lsl r2 290132718Skan orr xh, r5, xh, lsr r4 291132718Skan RETLDM "r4, r5" 292132718Skan 293132718Skan @ shift result right of 21 to 31 bits, or left 11 to 1 bits after 294132718Skan @ a register switch from xh to xl. 295132718Skan1: rsb r4, r4, #12 296132718Skan rsb r2, r4, #32 297132718Skan mov xl, xl, lsr r2 298132718Skan orr xl, xl, xh, lsl r4 299132718Skan mov xh, r5 300132718Skan RETLDM "r4, r5" 301132718Skan 302132718Skan @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch 303132718Skan @ from xh to xl. 304132718Skan2: mov xl, xh, lsr r4 305132718Skan mov xh, r5 306132718Skan RETLDM "r4, r5" 307132718Skan 308132718Skan @ Adjust exponents for denormalized arguments. 309169689Skan @ Note that r4 must not remain equal to 0. 310132718SkanLSYM(Lad_d): 311132718Skan teq r4, #0 312169689Skan eor yh, yh, #0x00100000 313132718Skan eoreq xh, xh, #0x00100000 314169689Skan addeq r4, r4, #1 315169689Skan subne r5, r5, #1 316132718Skan b LSYM(Lad_x) 317132718Skan 318169689Skan 319169689SkanLSYM(Lad_s): 320169689Skan mvns ip, r4, asr #21 321169689Skan mvnnes ip, r5, asr #21 322169689Skan beq LSYM(Lad_i) 323169689Skan 324169689Skan teq r4, r5 325169689Skan teqeq xl, yl 326169689Skan beq 1f 327169689Skan 328169689Skan @ Result is x + 0.0 = x or 0.0 + y = y. 329169689Skan orrs ip, r4, xl 330169689Skan moveq xh, yh 331169689Skan moveq xl, yl 332169689Skan RETLDM "r4, r5" 333169689Skan 334169689Skan1: teq xh, yh 335169689Skan 336169689Skan @ Result is x - x = 0. 337132718Skan movne xh, #0 338169689Skan movne xl, #0 339169689Skan RETLDM "r4, r5" ne 340132718Skan 341169689Skan @ Result is x + x = 2x. 342169689Skan movs ip, r4, lsr #21 343169689Skan bne 2f 344169689Skan movs xl, xl, lsl #1 345169689Skan adcs xh, xh, xh 346169689Skan orrcs xh, xh, #0x80000000 347169689Skan RETLDM "r4, r5" 348169689Skan2: adds r4, r4, #(2 << 21) 349169689Skan addcc xh, xh, #(1 << 20) 350169689Skan RETLDM "r4, r5" cc 351169689Skan and r5, xh, #0x80000000 352169689Skan 353132718Skan @ Overflow: return INF. 354132718SkanLSYM(Lad_o): 355132718Skan orr xh, r5, #0x7f000000 356132718Skan orr xh, xh, #0x00f00000 357132718Skan mov xl, #0 358132718Skan RETLDM "r4, r5" 359132718Skan 360132718Skan @ At least one of x or y is INF/NAN. 361132718Skan @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN) 362132718Skan @ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN) 363132718Skan @ if either is NAN: return NAN 364132718Skan @ if opposite sign: return NAN 365169689Skan @ otherwise return xh-xl (which is INF or -INF) 366132718SkanLSYM(Lad_i): 367169689Skan mvns ip, r4, asr #21 368132718Skan movne xh, yh 369132718Skan movne xl, yl 370169689Skan mvneqs ip, r5, asr #21 371169689Skan movne yh, xh 372169689Skan movne yl, xl 373132718Skan orrs r4, xl, xh, lsl #12 374169689Skan orreqs r5, yl, yh, lsl #12 375132718Skan teqeq xh, yh 376169689Skan orrne xh, xh, #0x00080000 @ quiet NAN 377132718Skan RETLDM "r4, r5" 378132718Skan 379169689Skan FUNC_END aeabi_dsub 380132718Skan FUNC_END subdf3 381169689Skan FUNC_END aeabi_dadd 382132718Skan FUNC_END adddf3 383132718Skan 384132718SkanARM_FUNC_START floatunsidf 385169689SkanARM_FUNC_ALIAS aeabi_ui2d floatunsidf 386169689Skan 387132718Skan teq r0, #0 388132718Skan moveq r1, #0 389132718Skan RETc(eq) 390132718Skan stmfd sp!, {r4, r5, lr} 391169689Skan mov r4, #0x400 @ initial exponent 392169689Skan add r4, r4, #(52-1 - 1) 393132718Skan mov r5, #0 @ sign bit is 0 394169689Skan .ifnc xl, r0 395132718Skan mov xl, r0 396169689Skan .endif 397132718Skan mov xh, #0 398132718Skan b LSYM(Lad_l) 399132718Skan 400169689Skan FUNC_END aeabi_ui2d 401132718Skan FUNC_END floatunsidf 402132718Skan 403132718SkanARM_FUNC_START floatsidf 404169689SkanARM_FUNC_ALIAS aeabi_i2d floatsidf 405169689Skan 406132718Skan teq r0, #0 407132718Skan moveq r1, #0 408132718Skan RETc(eq) 409132718Skan stmfd sp!, {r4, r5, lr} 410169689Skan mov r4, #0x400 @ initial exponent 411169689Skan add r4, r4, #(52-1 - 1) 412132718Skan ands r5, r0, #0x80000000 @ sign bit in r5 413132718Skan rsbmi r0, r0, #0 @ absolute value 414169689Skan .ifnc xl, r0 415132718Skan mov xl, r0 416169689Skan .endif 417132718Skan mov xh, #0 418132718Skan b LSYM(Lad_l) 419132718Skan 420169689Skan FUNC_END aeabi_i2d 421132718Skan FUNC_END floatsidf 422132718Skan 423132718SkanARM_FUNC_START extendsfdf2 424169689SkanARM_FUNC_ALIAS aeabi_f2d extendsfdf2 425169689Skan 426169689Skan movs r2, r0, lsl #1 @ toss sign bit 427132718Skan mov xh, r2, asr #3 @ stretch exponent 428132718Skan mov xh, xh, rrx @ retrieve sign bit 429132718Skan mov xl, r2, lsl #28 @ retrieve remaining bits 430169689Skan andnes r3, r2, #0xff000000 @ isolate exponent 431169689Skan teqne r3, #0xff000000 @ if not 0, check if INF or NAN 432132718Skan eorne xh, xh, #0x38000000 @ fixup exponent otherwise. 433169689Skan RETc(ne) @ and return it. 434132718Skan 435169689Skan teq r2, #0 @ if actually 0 436169689Skan teqne r3, #0xff000000 @ or INF or NAN 437169689Skan RETc(eq) @ we are done already. 438132718Skan 439169689Skan @ value was denormalized. We can normalize it now. 440132718Skan stmfd sp!, {r4, r5, lr} 441169689Skan mov r4, #0x380 @ setup corresponding exponent 442132718Skan and r5, xh, #0x80000000 @ move sign bit in r5 443132718Skan bic xh, xh, #0x80000000 444132718Skan b LSYM(Lad_l) 445132718Skan 446169689Skan FUNC_END aeabi_f2d 447132718Skan FUNC_END extendsfdf2 448132718Skan 449169689SkanARM_FUNC_START floatundidf 450169689SkanARM_FUNC_ALIAS aeabi_ul2d floatundidf 451169689Skan 452169689Skan orrs r2, r0, r1 453169689Skan#if !defined (__VFP_FP__) && !defined(__SOFTFP__) 454169689Skan mvfeqd f0, #0.0 455169689Skan#endif 456169689Skan RETc(eq) 457169689Skan 458169689Skan#if !defined (__VFP_FP__) && !defined(__SOFTFP__) 459169689Skan @ For hard FPA code we want to return via the tail below so that 460169689Skan @ we can return the result in f0 as well as in r0/r1 for backwards 461169689Skan @ compatibility. 462169689Skan adr ip, LSYM(f0_ret) 463169689Skan stmfd sp!, {r4, r5, ip, lr} 464169689Skan#else 465169689Skan stmfd sp!, {r4, r5, lr} 466169689Skan#endif 467169689Skan 468169689Skan mov r5, #0 469169689Skan b 2f 470169689Skan 471169689SkanARM_FUNC_START floatdidf 472169689SkanARM_FUNC_ALIAS aeabi_l2d floatdidf 473169689Skan 474169689Skan orrs r2, r0, r1 475169689Skan#if !defined (__VFP_FP__) && !defined(__SOFTFP__) 476169689Skan mvfeqd f0, #0.0 477169689Skan#endif 478169689Skan RETc(eq) 479169689Skan 480169689Skan#if !defined (__VFP_FP__) && !defined(__SOFTFP__) 481169689Skan @ For hard FPA code we want to return via the tail below so that 482169689Skan @ we can return the result in f0 as well as in r0/r1 for backwards 483169689Skan @ compatibility. 484169689Skan adr ip, LSYM(f0_ret) 485169689Skan stmfd sp!, {r4, r5, ip, lr} 486169689Skan#else 487169689Skan stmfd sp!, {r4, r5, lr} 488169689Skan#endif 489169689Skan 490169689Skan ands r5, ah, #0x80000000 @ sign bit in r5 491169689Skan bpl 2f 492169689Skan rsbs al, al, #0 493169689Skan rsc ah, ah, #0 494169689Skan2: 495169689Skan mov r4, #0x400 @ initial exponent 496169689Skan add r4, r4, #(52-1 - 1) 497169689Skan 498169689Skan @ FPA little-endian: must swap the word order. 499169689Skan .ifnc xh, ah 500169689Skan mov ip, al 501169689Skan mov xh, ah 502169689Skan mov xl, ip 503169689Skan .endif 504169689Skan 505169689Skan movs ip, xh, lsr #22 506169689Skan beq LSYM(Lad_p) 507169689Skan 508169689Skan @ The value is too big. Scale it down a bit... 509169689Skan mov r2, #3 510169689Skan movs ip, ip, lsr #3 511169689Skan addne r2, r2, #3 512169689Skan movs ip, ip, lsr #3 513169689Skan addne r2, r2, #3 514169689Skan add r2, r2, ip, lsr #3 515169689Skan 516169689Skan rsb r3, r2, #32 517169689Skan mov ip, xl, lsl r3 518169689Skan mov xl, xl, lsr r2 519169689Skan orr xl, xl, xh, lsl r3 520169689Skan mov xh, xh, lsr r2 521169689Skan add r4, r4, r2 522169689Skan b LSYM(Lad_p) 523169689Skan 524169689Skan#if !defined (__VFP_FP__) && !defined(__SOFTFP__) 525169689Skan 526169689Skan @ Legacy code expects the result to be returned in f0. Copy it 527169689Skan @ there as well. 528169689SkanLSYM(f0_ret): 529169689Skan stmfd sp!, {r0, r1} 530169689Skan ldfd f0, [sp], #8 531169689Skan RETLDM 532169689Skan 533169689Skan#endif 534169689Skan 535169689Skan FUNC_END floatdidf 536169689Skan FUNC_END aeabi_l2d 537169689Skan FUNC_END floatundidf 538169689Skan FUNC_END aeabi_ul2d 539169689Skan 540132718Skan#endif /* L_addsubdf3 */ 541132718Skan 542132718Skan#ifdef L_muldivdf3 543132718Skan 544132718SkanARM_FUNC_START muldf3 545169689SkanARM_FUNC_ALIAS aeabi_dmul muldf3 546132718Skan stmfd sp!, {r4, r5, r6, lr} 547132718Skan 548169689Skan @ Mask out exponents, trap any zero/denormal/INF/NAN. 549169689Skan mov ip, #0xff 550169689Skan orr ip, ip, #0x700 551169689Skan ands r4, ip, xh, lsr #20 552169689Skan andnes r5, ip, yh, lsr #20 553169689Skan teqne r4, ip 554132718Skan teqne r5, ip 555169689Skan bleq LSYM(Lml_s) 556132718Skan 557169689Skan @ Add exponents together 558169689Skan add r4, r4, r5 559132718Skan 560169689Skan @ Determine final sign. 561169689Skan eor r6, xh, yh 562132718Skan 563132718Skan @ Convert mantissa to unsigned integer. 564169689Skan @ If power of two, branch to a separate path. 565169689Skan bic xh, xh, ip, lsl #21 566169689Skan bic yh, yh, ip, lsl #21 567169689Skan orrs r5, xl, xh, lsl #12 568169689Skan orrnes r5, yl, yh, lsl #12 569132718Skan orr xh, xh, #0x00100000 570132718Skan orr yh, yh, #0x00100000 571169689Skan beq LSYM(Lml_1) 572132718Skan 573132718Skan#if __ARM_ARCH__ < 4 574132718Skan 575169689Skan @ Put sign bit in r6, which will be restored in yl later. 576169689Skan and r6, r6, #0x80000000 577169689Skan 578132718Skan @ Well, no way to make it shorter without the umull instruction. 579169689Skan stmfd sp!, {r6, r7, r8, r9, sl, fp} 580132718Skan mov r7, xl, lsr #16 581132718Skan mov r8, yl, lsr #16 582132718Skan mov r9, xh, lsr #16 583132718Skan mov sl, yh, lsr #16 584132718Skan bic xl, xl, r7, lsl #16 585132718Skan bic yl, yl, r8, lsl #16 586132718Skan bic xh, xh, r9, lsl #16 587132718Skan bic yh, yh, sl, lsl #16 588132718Skan mul ip, xl, yl 589132718Skan mul fp, xl, r8 590132718Skan mov lr, #0 591132718Skan adds ip, ip, fp, lsl #16 592132718Skan adc lr, lr, fp, lsr #16 593132718Skan mul fp, r7, yl 594132718Skan adds ip, ip, fp, lsl #16 595132718Skan adc lr, lr, fp, lsr #16 596132718Skan mul fp, xl, sl 597132718Skan mov r5, #0 598132718Skan adds lr, lr, fp, lsl #16 599132718Skan adc r5, r5, fp, lsr #16 600132718Skan mul fp, r7, yh 601132718Skan adds lr, lr, fp, lsl #16 602132718Skan adc r5, r5, fp, lsr #16 603132718Skan mul fp, xh, r8 604132718Skan adds lr, lr, fp, lsl #16 605132718Skan adc r5, r5, fp, lsr #16 606132718Skan mul fp, r9, yl 607132718Skan adds lr, lr, fp, lsl #16 608132718Skan adc r5, r5, fp, lsr #16 609132718Skan mul fp, xh, sl 610132718Skan mul r6, r9, sl 611132718Skan adds r5, r5, fp, lsl #16 612132718Skan adc r6, r6, fp, lsr #16 613132718Skan mul fp, r9, yh 614132718Skan adds r5, r5, fp, lsl #16 615132718Skan adc r6, r6, fp, lsr #16 616132718Skan mul fp, xl, yh 617132718Skan adds lr, lr, fp 618132718Skan mul fp, r7, sl 619132718Skan adcs r5, r5, fp 620132718Skan mul fp, xh, yl 621132718Skan adc r6, r6, #0 622132718Skan adds lr, lr, fp 623132718Skan mul fp, r9, r8 624132718Skan adcs r5, r5, fp 625132718Skan mul fp, r7, r8 626132718Skan adc r6, r6, #0 627132718Skan adds lr, lr, fp 628132718Skan mul fp, xh, yh 629132718Skan adcs r5, r5, fp 630132718Skan adc r6, r6, #0 631169689Skan ldmfd sp!, {yl, r7, r8, r9, sl, fp} 632132718Skan 633132718Skan#else 634132718Skan 635169689Skan @ Here is the actual multiplication. 636132718Skan umull ip, lr, xl, yl 637132718Skan mov r5, #0 638169689Skan umlal lr, r5, xh, yl 639169689Skan and yl, r6, #0x80000000 640132718Skan umlal lr, r5, xl, yh 641132718Skan mov r6, #0 642132718Skan umlal r5, r6, xh, yh 643132718Skan 644132718Skan#endif 645132718Skan 646132718Skan @ The LSBs in ip are only significant for the final rounding. 647169689Skan @ Fold them into lr. 648132718Skan teq ip, #0 649132718Skan orrne lr, lr, #1 650132718Skan 651169689Skan @ Adjust result upon the MSB position. 652169689Skan sub r4, r4, #0xff 653169689Skan cmp r6, #(1 << (20-11)) 654169689Skan sbc r4, r4, #0x300 655169689Skan bcs 1f 656169689Skan movs lr, lr, lsl #1 657169689Skan adcs r5, r5, r5 658169689Skan adc r6, r6, r6 659132718Skan1: 660169689Skan @ Shift to final position, add sign to result. 661169689Skan orr xh, yl, r6, lsl #11 662169689Skan orr xh, xh, r5, lsr #21 663169689Skan mov xl, r5, lsl #11 664169689Skan orr xl, xl, lr, lsr #21 665169689Skan mov lr, lr, lsl #11 666132718Skan 667169689Skan @ Check exponent range for under/overflow. 668169689Skan subs ip, r4, #(254 - 1) 669169689Skan cmphi ip, #0x700 670169689Skan bhi LSYM(Lml_u) 671132718Skan 672169689Skan @ Round the result, merge final exponent. 673169689Skan cmp lr, #0x80000000 674169689Skan moveqs lr, xl, lsr #1 675169689Skan adcs xl, xl, #0 676169689Skan adc xh, xh, r4, lsl #20 677132718Skan RETLDM "r4, r5, r6" 678132718Skan 679169689Skan @ Multiplication by 0x1p*: let''s shortcut a lot of code. 680169689SkanLSYM(Lml_1): 681169689Skan and r6, r6, #0x80000000 682169689Skan orr xh, r6, xh 683169689Skan orr xl, xl, yl 684132718Skan eor xh, xh, yh 685169689Skan subs r4, r4, ip, lsr #1 686169689Skan rsbgts r5, r4, ip 687169689Skan orrgt xh, xh, r4, lsl #20 688169689Skan RETLDM "r4, r5, r6" gt 689132718Skan 690169689Skan @ Under/overflow: fix things up for the code below. 691169689Skan orr xh, xh, #0x00100000 692169689Skan mov lr, #0 693169689Skan subs r4, r4, #1 694169689Skan 695169689SkanLSYM(Lml_u): 696169689Skan @ Overflow? 697169689Skan bgt LSYM(Lml_o) 698169689Skan 699132718Skan @ Check if denormalized result is possible, otherwise return signed 0. 700169689Skan cmn r4, #(53 + 1) 701132718Skan movle xl, #0 702132718Skan bicle xh, xh, #0x7fffffff 703132718Skan RETLDM "r4, r5, r6" le 704132718Skan 705132718Skan @ Find out proper shift value. 706169689Skan rsb r4, r4, #0 707169689Skan subs r4, r4, #32 708132718Skan bge 2f 709132718Skan adds r4, r4, #12 710132718Skan bgt 1f 711132718Skan 712132718Skan @ shift result right of 1 to 20 bits, preserve sign bit, round, etc. 713132718Skan add r4, r4, #20 714132718Skan rsb r5, r4, #32 715132718Skan mov r3, xl, lsl r5 716132718Skan mov xl, xl, lsr r4 717132718Skan orr xl, xl, xh, lsl r5 718169689Skan and r2, xh, #0x80000000 719169689Skan bic xh, xh, #0x80000000 720132718Skan adds xl, xl, r3, lsr #31 721169689Skan adc xh, r2, xh, lsr r4 722169689Skan orrs lr, lr, r3, lsl #1 723169689Skan biceq xl, xl, r3, lsr #31 724132718Skan RETLDM "r4, r5, r6" 725132718Skan 726132718Skan @ shift result right of 21 to 31 bits, or left 11 to 1 bits after 727132718Skan @ a register switch from xh to xl. Then round. 728132718Skan1: rsb r4, r4, #12 729132718Skan rsb r5, r4, #32 730132718Skan mov r3, xl, lsl r4 731132718Skan mov xl, xl, lsr r5 732132718Skan orr xl, xl, xh, lsl r4 733132718Skan bic xh, xh, #0x7fffffff 734132718Skan adds xl, xl, r3, lsr #31 735132718Skan adc xh, xh, #0 736169689Skan orrs lr, lr, r3, lsl #1 737169689Skan biceq xl, xl, r3, lsr #31 738132718Skan RETLDM "r4, r5, r6" 739132718Skan 740132718Skan @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch 741132718Skan @ from xh to xl. Leftover bits are in r3-r6-lr for rounding. 742132718Skan2: rsb r5, r4, #32 743169689Skan orr lr, lr, xl, lsl r5 744132718Skan mov r3, xl, lsr r4 745132718Skan orr r3, r3, xh, lsl r5 746132718Skan mov xl, xh, lsr r4 747132718Skan bic xh, xh, #0x7fffffff 748132718Skan bic xl, xl, xh, lsr r4 749132718Skan add xl, xl, r3, lsr #31 750169689Skan orrs lr, lr, r3, lsl #1 751169689Skan biceq xl, xl, r3, lsr #31 752132718Skan RETLDM "r4, r5, r6" 753132718Skan 754132718Skan @ One or both arguments are denormalized. 755132718Skan @ Scale them leftwards and preserve sign bit. 756132718SkanLSYM(Lml_d): 757132718Skan teq r4, #0 758132718Skan bne 2f 759132718Skan and r6, xh, #0x80000000 760132718Skan1: movs xl, xl, lsl #1 761169689Skan adc xh, xh, xh 762132718Skan tst xh, #0x00100000 763169689Skan subeq r4, r4, #1 764132718Skan beq 1b 765132718Skan orr xh, xh, r6 766132718Skan teq r5, #0 767169689Skan movne pc, lr 768132718Skan2: and r6, yh, #0x80000000 769132718Skan3: movs yl, yl, lsl #1 770169689Skan adc yh, yh, yh 771132718Skan tst yh, #0x00100000 772169689Skan subeq r5, r5, #1 773132718Skan beq 3b 774132718Skan orr yh, yh, r6 775169689Skan mov pc, lr 776132718Skan 777132718SkanLSYM(Lml_s): 778169689Skan @ Isolate the INF and NAN cases away 779169689Skan teq r4, ip 780169689Skan and r5, ip, yh, lsr #20 781169689Skan teqne r5, ip 782169689Skan beq 1f 783169689Skan 784169689Skan @ Here, one or more arguments are either denormalized or zero. 785132718Skan orrs r6, xl, xh, lsl #1 786132718Skan orrnes r6, yl, yh, lsl #1 787169689Skan bne LSYM(Lml_d) 788169689Skan 789169689Skan @ Result is 0, but determine sign anyway. 790169689SkanLSYM(Lml_z): 791169689Skan eor xh, xh, yh 792169689Skan bic xh, xh, #0x7fffffff 793169689Skan mov xl, #0 794169689Skan RETLDM "r4, r5, r6" 795169689Skan 796169689Skan1: @ One or both args are INF or NAN. 797169689Skan orrs r6, xl, xh, lsl #1 798169689Skan moveq xl, yl 799169689Skan moveq xh, yh 800169689Skan orrnes r6, yl, yh, lsl #1 801132718Skan beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN 802132718Skan teq r4, ip 803132718Skan bne 1f 804132718Skan orrs r6, xl, xh, lsl #12 805132718Skan bne LSYM(Lml_n) @ NAN * <anything> -> NAN 806132718Skan1: teq r5, ip 807132718Skan bne LSYM(Lml_i) 808132718Skan orrs r6, yl, yh, lsl #12 809169689Skan movne xl, yl 810169689Skan movne xh, yh 811132718Skan bne LSYM(Lml_n) @ <anything> * NAN -> NAN 812132718Skan 813132718Skan @ Result is INF, but we need to determine its sign. 814132718SkanLSYM(Lml_i): 815132718Skan eor xh, xh, yh 816132718Skan 817132718Skan @ Overflow: return INF (sign already in xh). 818132718SkanLSYM(Lml_o): 819132718Skan and xh, xh, #0x80000000 820132718Skan orr xh, xh, #0x7f000000 821132718Skan orr xh, xh, #0x00f00000 822132718Skan mov xl, #0 823132718Skan RETLDM "r4, r5, r6" 824132718Skan 825169689Skan @ Return a quiet NAN. 826132718SkanLSYM(Lml_n): 827169689Skan orr xh, xh, #0x7f000000 828132718Skan orr xh, xh, #0x00f80000 829132718Skan RETLDM "r4, r5, r6" 830132718Skan 831169689Skan FUNC_END aeabi_dmul 832132718Skan FUNC_END muldf3 833132718Skan 834132718SkanARM_FUNC_START divdf3 835169689SkanARM_FUNC_ALIAS aeabi_ddiv divdf3 836169689Skan 837132718Skan stmfd sp!, {r4, r5, r6, lr} 838132718Skan 839169689Skan @ Mask out exponents, trap any zero/denormal/INF/NAN. 840169689Skan mov ip, #0xff 841169689Skan orr ip, ip, #0x700 842169689Skan ands r4, ip, xh, lsr #20 843169689Skan andnes r5, ip, yh, lsr #20 844169689Skan teqne r4, ip 845132718Skan teqne r5, ip 846169689Skan bleq LSYM(Ldv_s) 847132718Skan 848169689Skan @ Substract divisor exponent from dividend''s. 849169689Skan sub r4, r4, r5 850132718Skan 851132718Skan @ Preserve final sign into lr. 852132718Skan eor lr, xh, yh 853132718Skan 854132718Skan @ Convert mantissa to unsigned integer. 855132718Skan @ Dividend -> r5-r6, divisor -> yh-yl. 856169689Skan orrs r5, yl, yh, lsl #12 857169689Skan mov xh, xh, lsl #12 858169689Skan beq LSYM(Ldv_1) 859169689Skan mov yh, yh, lsl #12 860132718Skan mov r5, #0x10000000 861132718Skan orr yh, r5, yh, lsr #4 862132718Skan orr yh, yh, yl, lsr #24 863169689Skan mov yl, yl, lsl #8 864132718Skan orr r5, r5, xh, lsr #4 865132718Skan orr r5, r5, xl, lsr #24 866132718Skan mov r6, xl, lsl #8 867132718Skan 868132718Skan @ Initialize xh with final sign bit. 869132718Skan and xh, lr, #0x80000000 870132718Skan 871132718Skan @ Ensure result will land to known bit position. 872169689Skan @ Apply exponent bias accordingly. 873132718Skan cmp r5, yh 874132718Skan cmpeq r6, yl 875169689Skan adc r4, r4, #(255 - 2) 876169689Skan add r4, r4, #0x300 877132718Skan bcs 1f 878132718Skan movs yh, yh, lsr #1 879132718Skan mov yl, yl, rrx 880132718Skan1: 881132718Skan @ Perform first substraction to align result to a nibble. 882132718Skan subs r6, r6, yl 883132718Skan sbc r5, r5, yh 884132718Skan movs yh, yh, lsr #1 885132718Skan mov yl, yl, rrx 886132718Skan mov xl, #0x00100000 887132718Skan mov ip, #0x00080000 888132718Skan 889132718Skan @ The actual division loop. 890132718Skan1: subs lr, r6, yl 891132718Skan sbcs lr, r5, yh 892132718Skan subcs r6, r6, yl 893132718Skan movcs r5, lr 894132718Skan orrcs xl, xl, ip 895132718Skan movs yh, yh, lsr #1 896132718Skan mov yl, yl, rrx 897132718Skan subs lr, r6, yl 898132718Skan sbcs lr, r5, yh 899132718Skan subcs r6, r6, yl 900132718Skan movcs r5, lr 901132718Skan orrcs xl, xl, ip, lsr #1 902132718Skan movs yh, yh, lsr #1 903132718Skan mov yl, yl, rrx 904132718Skan subs lr, r6, yl 905132718Skan sbcs lr, r5, yh 906132718Skan subcs r6, r6, yl 907132718Skan movcs r5, lr 908132718Skan orrcs xl, xl, ip, lsr #2 909132718Skan movs yh, yh, lsr #1 910132718Skan mov yl, yl, rrx 911132718Skan subs lr, r6, yl 912132718Skan sbcs lr, r5, yh 913132718Skan subcs r6, r6, yl 914132718Skan movcs r5, lr 915132718Skan orrcs xl, xl, ip, lsr #3 916132718Skan 917132718Skan orrs lr, r5, r6 918132718Skan beq 2f 919132718Skan mov r5, r5, lsl #4 920132718Skan orr r5, r5, r6, lsr #28 921132718Skan mov r6, r6, lsl #4 922132718Skan mov yh, yh, lsl #3 923132718Skan orr yh, yh, yl, lsr #29 924132718Skan mov yl, yl, lsl #3 925132718Skan movs ip, ip, lsr #4 926132718Skan bne 1b 927132718Skan 928132718Skan @ We are done with a word of the result. 929132718Skan @ Loop again for the low word if this pass was for the high word. 930132718Skan tst xh, #0x00100000 931132718Skan bne 3f 932132718Skan orr xh, xh, xl 933132718Skan mov xl, #0 934132718Skan mov ip, #0x80000000 935132718Skan b 1b 936132718Skan2: 937132718Skan @ Be sure result starts in the high word. 938132718Skan tst xh, #0x00100000 939132718Skan orreq xh, xh, xl 940132718Skan moveq xl, #0 941132718Skan3: 942169689Skan @ Check exponent range for under/overflow. 943169689Skan subs ip, r4, #(254 - 1) 944169689Skan cmphi ip, #0x700 945169689Skan bhi LSYM(Lml_u) 946132718Skan 947169689Skan @ Round the result, merge final exponent. 948132718Skan subs ip, r5, yh 949132718Skan subeqs ip, r6, yl 950169689Skan moveqs ip, xl, lsr #1 951132718Skan adcs xl, xl, #0 952169689Skan adc xh, xh, r4, lsl #20 953132718Skan RETLDM "r4, r5, r6" 954132718Skan 955132718Skan @ Division by 0x1p*: shortcut a lot of code. 956132718SkanLSYM(Ldv_1): 957132718Skan and lr, lr, #0x80000000 958132718Skan orr xh, lr, xh, lsr #12 959169689Skan adds r4, r4, ip, lsr #1 960169689Skan rsbgts r5, r4, ip 961169689Skan orrgt xh, xh, r4, lsl #20 962132718Skan RETLDM "r4, r5, r6" gt 963132718Skan 964132718Skan orr xh, xh, #0x00100000 965132718Skan mov lr, #0 966169689Skan subs r4, r4, #1 967169689Skan b LSYM(Lml_u) 968132718Skan 969169689Skan @ Result mightt need to be denormalized: put remainder bits 970169689Skan @ in lr for rounding considerations. 971132718SkanLSYM(Ldv_u): 972132718Skan orr lr, r5, r6 973169689Skan b LSYM(Lml_u) 974132718Skan 975132718Skan @ One or both arguments is either INF, NAN or zero. 976132718SkanLSYM(Ldv_s): 977169689Skan and r5, ip, yh, lsr #20 978132718Skan teq r4, ip 979132718Skan teqeq r5, ip 980132718Skan beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN 981132718Skan teq r4, ip 982132718Skan bne 1f 983132718Skan orrs r4, xl, xh, lsl #12 984132718Skan bne LSYM(Lml_n) @ NAN / <anything> -> NAN 985169689Skan teq r5, ip 986169689Skan bne LSYM(Lml_i) @ INF / <anything> -> INF 987169689Skan mov xl, yl 988169689Skan mov xh, yh 989169689Skan b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN 990132718Skan1: teq r5, ip 991132718Skan bne 2f 992132718Skan orrs r5, yl, yh, lsl #12 993169689Skan beq LSYM(Lml_z) @ <anything> / INF -> 0 994169689Skan mov xl, yl 995169689Skan mov xh, yh 996169689Skan b LSYM(Lml_n) @ <anything> / NAN -> NAN 997169689Skan2: @ If both are nonzero, we need to normalize and resume above. 998169689Skan orrs r6, xl, xh, lsl #1 999169689Skan orrnes r6, yl, yh, lsl #1 1000169689Skan bne LSYM(Lml_d) 1001169689Skan @ One or both arguments are 0. 1002132718Skan orrs r4, xl, xh, lsl #1 1003132718Skan bne LSYM(Lml_i) @ <non_zero> / 0 -> INF 1004132718Skan orrs r5, yl, yh, lsl #1 1005132718Skan bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 1006132718Skan b LSYM(Lml_n) @ 0 / 0 -> NAN 1007132718Skan 1008169689Skan FUNC_END aeabi_ddiv 1009132718Skan FUNC_END divdf3 1010132718Skan 1011132718Skan#endif /* L_muldivdf3 */ 1012132718Skan 1013132718Skan#ifdef L_cmpdf2 1014132718Skan 1015169689Skan@ Note: only r0 (return value) and ip are clobbered here. 1016169689Skan 1017132718SkanARM_FUNC_START gtdf2 1018132718SkanARM_FUNC_ALIAS gedf2 gtdf2 1019132718Skan mov ip, #-1 1020132718Skan b 1f 1021132718Skan 1022132718SkanARM_FUNC_START ltdf2 1023132718SkanARM_FUNC_ALIAS ledf2 ltdf2 1024132718Skan mov ip, #1 1025132718Skan b 1f 1026132718Skan 1027132718SkanARM_FUNC_START cmpdf2 1028132718SkanARM_FUNC_ALIAS nedf2 cmpdf2 1029132718SkanARM_FUNC_ALIAS eqdf2 cmpdf2 1030132718Skan mov ip, #1 @ how should we specify unordered here? 1031132718Skan 1032169689Skan1: str ip, [sp, #-4] 1033132718Skan 1034132718Skan @ Trap any INF/NAN first. 1035169689Skan mov ip, xh, lsl #1 1036169689Skan mvns ip, ip, asr #21 1037169689Skan mov ip, yh, lsl #1 1038169689Skan mvnnes ip, ip, asr #21 1039132718Skan beq 3f 1040132718Skan 1041132718Skan @ Test for equality. 1042132718Skan @ Note that 0.0 is equal to -0.0. 1043132718Skan2: orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0 1044132718Skan orreqs ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0 1045132718Skan teqne xh, yh @ or xh == yh 1046132718Skan teqeq xl, yl @ and xl == yl 1047132718Skan moveq r0, #0 @ then equal. 1048169689Skan RETc(eq) 1049132718Skan 1050169689Skan @ Clear C flag 1051169689Skan cmn r0, #0 1052169689Skan 1053169689Skan @ Compare sign, 1054132718Skan teq xh, yh 1055132718Skan 1056169689Skan @ Compare values if same sign 1057169689Skan cmppl xh, yh 1058169689Skan cmpeq xl, yl 1059132718Skan 1060169689Skan @ Result: 1061132718Skan movcs r0, yh, asr #31 1062132718Skan mvncc r0, yh, asr #31 1063132718Skan orr r0, r0, #1 1064169689Skan RET 1065132718Skan 1066132718Skan @ Look for a NAN. 1067169689Skan3: mov ip, xh, lsl #1 1068169689Skan mvns ip, ip, asr #21 1069132718Skan bne 4f 1070169689Skan orrs ip, xl, xh, lsl #12 1071132718Skan bne 5f @ x is NAN 1072169689Skan4: mov ip, yh, lsl #1 1073169689Skan mvns ip, ip, asr #21 1074132718Skan bne 2b 1075169689Skan orrs ip, yl, yh, lsl #12 1076132718Skan beq 2b @ y is not NAN 1077169689Skan5: ldr r0, [sp, #-4] @ unordered return code 1078169689Skan RET 1079132718Skan 1080132718Skan FUNC_END gedf2 1081132718Skan FUNC_END gtdf2 1082132718Skan FUNC_END ledf2 1083132718Skan FUNC_END ltdf2 1084132718Skan FUNC_END nedf2 1085132718Skan FUNC_END eqdf2 1086132718Skan FUNC_END cmpdf2 1087132718Skan 1088169689SkanARM_FUNC_START aeabi_cdrcmple 1089169689Skan 1090169689Skan mov ip, r0 1091169689Skan mov r0, r2 1092169689Skan mov r2, ip 1093169689Skan mov ip, r1 1094169689Skan mov r1, r3 1095169689Skan mov r3, ip 1096169689Skan b 6f 1097169689Skan 1098169689SkanARM_FUNC_START aeabi_cdcmpeq 1099169689SkanARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq 1100169689Skan 1101169689Skan @ The status-returning routines are required to preserve all 1102169689Skan @ registers except ip, lr, and cpsr. 1103169689Skan6: stmfd sp!, {r0, lr} 1104169689Skan ARM_CALL cmpdf2 1105169689Skan @ Set the Z flag correctly, and the C flag unconditionally. 1106169689Skan cmp r0, #0 1107169689Skan @ Clear the C flag if the return value was -1, indicating 1108169689Skan @ that the first operand was smaller than the second. 1109169689Skan cmnmi r0, #0 1110169689Skan RETLDM "r0" 1111169689Skan 1112169689Skan FUNC_END aeabi_cdcmple 1113169689Skan FUNC_END aeabi_cdcmpeq 1114169689Skan FUNC_END aeabi_cdrcmple 1115169689Skan 1116169689SkanARM_FUNC_START aeabi_dcmpeq 1117169689Skan 1118169689Skan str lr, [sp, #-8]! 1119169689Skan ARM_CALL aeabi_cdcmple 1120169689Skan moveq r0, #1 @ Equal to. 1121169689Skan movne r0, #0 @ Less than, greater than, or unordered. 1122169689Skan RETLDM 1123169689Skan 1124169689Skan FUNC_END aeabi_dcmpeq 1125169689Skan 1126169689SkanARM_FUNC_START aeabi_dcmplt 1127169689Skan 1128169689Skan str lr, [sp, #-8]! 1129169689Skan ARM_CALL aeabi_cdcmple 1130169689Skan movcc r0, #1 @ Less than. 1131169689Skan movcs r0, #0 @ Equal to, greater than, or unordered. 1132169689Skan RETLDM 1133169689Skan 1134169689Skan FUNC_END aeabi_dcmplt 1135169689Skan 1136169689SkanARM_FUNC_START aeabi_dcmple 1137169689Skan 1138169689Skan str lr, [sp, #-8]! 1139169689Skan ARM_CALL aeabi_cdcmple 1140169689Skan movls r0, #1 @ Less than or equal to. 1141169689Skan movhi r0, #0 @ Greater than or unordered. 1142169689Skan RETLDM 1143169689Skan 1144169689Skan FUNC_END aeabi_dcmple 1145169689Skan 1146169689SkanARM_FUNC_START aeabi_dcmpge 1147169689Skan 1148169689Skan str lr, [sp, #-8]! 1149169689Skan ARM_CALL aeabi_cdrcmple 1150169689Skan movls r0, #1 @ Operand 2 is less than or equal to operand 1. 1151169689Skan movhi r0, #0 @ Operand 2 greater than operand 1, or unordered. 1152169689Skan RETLDM 1153169689Skan 1154169689Skan FUNC_END aeabi_dcmpge 1155169689Skan 1156169689SkanARM_FUNC_START aeabi_dcmpgt 1157169689Skan 1158169689Skan str lr, [sp, #-8]! 1159169689Skan ARM_CALL aeabi_cdrcmple 1160169689Skan movcc r0, #1 @ Operand 2 is less than operand 1. 1161169689Skan movcs r0, #0 @ Operand 2 is greater than or equal to operand 1, 1162169689Skan @ or they are unordered. 1163169689Skan RETLDM 1164169689Skan 1165169689Skan FUNC_END aeabi_dcmpgt 1166169689Skan 1167132718Skan#endif /* L_cmpdf2 */ 1168132718Skan 1169132718Skan#ifdef L_unorddf2 1170132718Skan 1171132718SkanARM_FUNC_START unorddf2 1172169689SkanARM_FUNC_ALIAS aeabi_dcmpun unorddf2 1173169689Skan 1174169689Skan mov ip, xh, lsl #1 1175169689Skan mvns ip, ip, asr #21 1176132718Skan bne 1f 1177169689Skan orrs ip, xl, xh, lsl #12 1178132718Skan bne 3f @ x is NAN 1179169689Skan1: mov ip, yh, lsl #1 1180169689Skan mvns ip, ip, asr #21 1181132718Skan bne 2f 1182169689Skan orrs ip, yl, yh, lsl #12 1183132718Skan bne 3f @ y is NAN 1184132718Skan2: mov r0, #0 @ arguments are ordered. 1185169689Skan RET 1186132718Skan 1187132718Skan3: mov r0, #1 @ arguments are unordered. 1188169689Skan RET 1189132718Skan 1190169689Skan FUNC_END aeabi_dcmpun 1191132718Skan FUNC_END unorddf2 1192132718Skan 1193132718Skan#endif /* L_unorddf2 */ 1194132718Skan 1195132718Skan#ifdef L_fixdfsi 1196132718Skan 1197132718SkanARM_FUNC_START fixdfsi 1198169689SkanARM_FUNC_ALIAS aeabi_d2iz fixdfsi 1199132718Skan 1200132718Skan @ check exponent range. 1201169689Skan mov r2, xh, lsl #1 1202169689Skan adds r2, r2, #(1 << 21) 1203169689Skan bcs 2f @ value is INF or NAN 1204169689Skan bpl 1f @ value is too small 1205169689Skan mov r3, #(0xfffffc00 + 31) 1206169689Skan subs r2, r3, r2, asr #21 1207169689Skan bls 3f @ value is too large 1208132718Skan 1209169689Skan @ scale value 1210169689Skan mov r3, xh, lsl #11 1211169689Skan orr r3, r3, #0x80000000 1212169689Skan orr r3, r3, xl, lsr #21 1213169689Skan tst xh, #0x80000000 @ the sign bit 1214169689Skan mov r0, r3, lsr r2 1215132718Skan rsbne r0, r0, #0 1216132718Skan RET 1217132718Skan 1218132718Skan1: mov r0, #0 1219132718Skan RET 1220132718Skan 1221132718Skan2: orrs xl, xl, xh, lsl #12 1222169689Skan bne 4f @ x is NAN. 1223169689Skan3: ands r0, xh, #0x80000000 @ the sign bit 1224132718Skan moveq r0, #0x7fffffff @ maximum signed positive si 1225132718Skan RET 1226132718Skan 1227132718Skan4: mov r0, #0 @ How should we convert NAN? 1228132718Skan RET 1229132718Skan 1230169689Skan FUNC_END aeabi_d2iz 1231132718Skan FUNC_END fixdfsi 1232132718Skan 1233132718Skan#endif /* L_fixdfsi */ 1234132718Skan 1235132718Skan#ifdef L_fixunsdfsi 1236132718Skan 1237132718SkanARM_FUNC_START fixunsdfsi 1238169689SkanARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi 1239132718Skan 1240132718Skan @ check exponent range. 1241169689Skan movs r2, xh, lsl #1 1242169689Skan bcs 1f @ value is negative 1243169689Skan adds r2, r2, #(1 << 21) 1244169689Skan bcs 2f @ value is INF or NAN 1245169689Skan bpl 1f @ value is too small 1246169689Skan mov r3, #(0xfffffc00 + 31) 1247169689Skan subs r2, r3, r2, asr #21 1248169689Skan bmi 3f @ value is too large 1249132718Skan 1250169689Skan @ scale value 1251169689Skan mov r3, xh, lsl #11 1252169689Skan orr r3, r3, #0x80000000 1253169689Skan orr r3, r3, xl, lsr #21 1254169689Skan mov r0, r3, lsr r2 1255132718Skan RET 1256132718Skan 1257132718Skan1: mov r0, #0 1258132718Skan RET 1259132718Skan 1260132718Skan2: orrs xl, xl, xh, lsl #12 1261132718Skan bne 4f @ value is NAN. 1262132718Skan3: mov r0, #0xffffffff @ maximum unsigned si 1263132718Skan RET 1264132718Skan 1265132718Skan4: mov r0, #0 @ How should we convert NAN? 1266132718Skan RET 1267132718Skan 1268169689Skan FUNC_END aeabi_d2uiz 1269132718Skan FUNC_END fixunsdfsi 1270132718Skan 1271132718Skan#endif /* L_fixunsdfsi */ 1272132718Skan 1273132718Skan#ifdef L_truncdfsf2 1274132718Skan 1275132718SkanARM_FUNC_START truncdfsf2 1276169689SkanARM_FUNC_ALIAS aeabi_d2f truncdfsf2 1277169689Skan 1278132718Skan @ check exponent range. 1279169689Skan mov r2, xh, lsl #1 1280169689Skan subs r3, r2, #((1023 - 127) << 21) 1281169689Skan subcss ip, r3, #(1 << 21) 1282169689Skan rsbcss ip, ip, #(254 << 21) 1283169689Skan bls 2f @ value is out of range 1284132718Skan 1285169689Skan1: @ shift and round mantissa 1286169689Skan and ip, xh, #0x80000000 1287169689Skan mov r2, xl, lsl #3 1288169689Skan orr xl, ip, xl, lsr #29 1289169689Skan cmp r2, #0x80000000 1290169689Skan adc r0, xl, r3, lsl #2 1291169689Skan biceq r0, r0, #1 1292169689Skan RET 1293132718Skan 1294169689Skan2: @ either overflow or underflow 1295169689Skan tst xh, #0x40000000 1296169689Skan bne 3f @ overflow 1297132718Skan 1298169689Skan @ check if denormalized value is possible 1299169689Skan adds r2, r3, #(23 << 21) 1300169689Skan andlt r0, xh, #0x80000000 @ too small, return signed 0. 1301169689Skan RETc(lt) 1302132718Skan 1303169689Skan @ denormalize value so we can resume with the code above afterwards. 1304169689Skan orr xh, xh, #0x00100000 1305169689Skan mov r2, r2, lsr #21 1306169689Skan rsb r2, r2, #24 1307169689Skan rsb ip, r2, #32 1308169689Skan movs r3, xl, lsl ip 1309169689Skan mov xl, xl, lsr r2 1310169689Skan orrne xl, xl, #1 @ fold r3 for rounding considerations. 1311169689Skan mov r3, xh, lsl #11 1312169689Skan mov r3, r3, lsr #11 1313169689Skan orr xl, xl, r3, lsl ip 1314169689Skan mov r3, r3, lsr r2 1315169689Skan mov r3, r3, lsl #1 1316169689Skan b 1b 1317132718Skan 1318169689Skan3: @ chech for NAN 1319169689Skan mvns r3, r2, asr #21 1320169689Skan bne 5f @ simple overflow 1321169689Skan orrs r3, xl, xh, lsl #12 1322132718Skan movne r0, #0x7f000000 1323132718Skan orrne r0, r0, #0x00c00000 1324132718Skan RETc(ne) @ return NAN 1325132718Skan 1326169689Skan5: @ return INF with sign 1327132718Skan and r0, xh, #0x80000000 1328132718Skan orr r0, r0, #0x7f000000 1329132718Skan orr r0, r0, #0x00800000 1330132718Skan RET 1331132718Skan 1332169689Skan FUNC_END aeabi_d2f 1333132718Skan FUNC_END truncdfsf2 1334132718Skan 1335132718Skan#endif /* L_truncdfsf2 */ 1336