1 1.1 mrg /* libgcc routines for 68000 w/o floating-point hardware. 2 1.11 mrg Copyright (C) 1994-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify it 7 1.1 mrg under the terms of the GNU General Public License as published by the 8 1.1 mrg Free Software Foundation; either version 3, or (at your option) any 9 1.1 mrg later version. 10 1.1 mrg 11 1.1 mrg This file is distributed in the hope that it will be useful, but 12 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 1.1 mrg General Public License for more details. 15 1.1 mrg 16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg You should have received a copy of the GNU General Public License and 21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg <http://www.gnu.org/licenses/>. */ 24 1.1 mrg 25 1.1 mrg /* Use this one for any 680x0; assumes no floating point hardware. 26 1.1 mrg The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. 27 1.1 mrg Some of this code comes from MINIX, via the folks at ericsson. 28 1.1 mrg D. V. Henkel-Wallace (gumby (at) cygnus.com) Fete Bastille, 1992 29 1.1 mrg */ 30 1.1 mrg 31 1.1 mrg /* These are predefined by new versions of GNU cpp. */ 32 1.1 mrg 33 1.1 mrg #ifndef __USER_LABEL_PREFIX__ 34 1.1 mrg #define __USER_LABEL_PREFIX__ _ 35 1.1 mrg #endif 36 1.1 mrg 37 1.1 mrg #ifndef __REGISTER_PREFIX__ 38 1.1 mrg #define __REGISTER_PREFIX__ 39 1.1 mrg #endif 40 1.1 mrg 41 1.1 mrg #ifndef __IMMEDIATE_PREFIX__ 42 1.1 mrg #define __IMMEDIATE_PREFIX__ # 43 1.1 mrg #endif 44 1.1 mrg 45 1.1 mrg /* ANSI concatenation macros. */ 46 1.1 mrg 47 1.1 mrg #define CONCAT1(a, b) CONCAT2(a, b) 48 1.1 mrg #define CONCAT2(a, b) a ## b 49 1.1 mrg 50 1.1 mrg /* Use the right prefix for global labels. */ 51 1.1 mrg 52 1.1 mrg #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) 53 1.1 mrg 54 1.1 mrg /* Note that X is a function. */ 55 1.1 mrg 56 1.1 mrg #ifdef __ELF__ 57 1.1 mrg #define FUNC(x) .type SYM(x),function 58 1.1 mrg #else 59 1.1 mrg /* The .proc pseudo-op is accepted, but ignored, by GAS. We could just 60 1.1 mrg define this to the empty string for non-ELF systems, but defining it 61 1.1 mrg to .proc means that the information is available to the assembler if 62 1.1 mrg the need arises. */ 63 1.1 mrg #define FUNC(x) .proc 64 1.1 mrg #endif 65 1.1 mrg 66 1.1 mrg /* Use the right prefix for registers. */ 67 1.1 mrg 68 1.1 mrg #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) 69 1.1 mrg 70 1.1 mrg /* Use the right prefix for immediate values. */ 71 1.1 mrg 72 1.1 mrg #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) 73 1.1 mrg 74 1.1 mrg #define d0 REG (d0) 75 1.1 mrg #define d1 REG (d1) 76 1.1 mrg #define d2 REG (d2) 77 1.1 mrg #define d3 REG (d3) 78 1.1 mrg #define d4 REG (d4) 79 1.1 mrg #define d5 REG (d5) 80 1.1 mrg #define d6 REG (d6) 81 1.1 mrg #define d7 REG (d7) 82 1.1 mrg #define a0 REG (a0) 83 1.1 mrg #define a1 REG (a1) 84 1.1 mrg #define a2 REG (a2) 85 1.1 mrg #define a3 REG (a3) 86 1.1 mrg #define a4 REG (a4) 87 1.1 mrg #define a5 REG (a5) 88 1.1 mrg #define a6 REG (a6) 89 1.1 mrg #define fp REG (fp) 90 1.1 mrg #define sp REG (sp) 91 1.1 mrg #define pc REG (pc) 92 1.1 mrg 93 1.1 mrg /* Provide a few macros to allow for PIC code support. 94 1.1 mrg * With PIC, data is stored A5 relative so we've got to take a bit of special 95 1.1 mrg * care to ensure that all loads of global data is via A5. PIC also requires 96 1.1 mrg * jumps and subroutine calls to be PC relative rather than absolute. We cheat 97 1.1 mrg * a little on this and in the PIC case, we use short offset branches and 98 1.1 mrg * hope that the final object code is within range (which it should be). 99 1.1 mrg */ 100 1.1 mrg #ifndef __PIC__ 101 1.1 mrg 102 1.1 mrg /* Non PIC (absolute/relocatable) versions */ 103 1.1 mrg 104 1.1 mrg .macro PICCALL addr 105 1.1 mrg jbsr \addr 106 1.1 mrg .endm 107 1.1 mrg 108 1.1 mrg .macro PICJUMP addr 109 1.1 mrg jmp \addr 110 1.1 mrg .endm 111 1.1 mrg 112 1.1 mrg .macro PICLEA sym, reg 113 1.1 mrg lea \sym, \reg 114 1.1 mrg .endm 115 1.1 mrg 116 1.1 mrg .macro PICPEA sym, areg 117 1.1 mrg pea \sym 118 1.1 mrg .endm 119 1.1 mrg 120 1.1 mrg #else /* __PIC__ */ 121 1.1 mrg 122 1.1 mrg # if defined (__uClinux__) 123 1.1 mrg 124 1.1 mrg /* Versions for uClinux */ 125 1.1 mrg 126 1.1 mrg # if defined(__ID_SHARED_LIBRARY__) 127 1.1 mrg 128 1.1 mrg /* -mid-shared-library versions */ 129 1.1 mrg 130 1.1 mrg .macro PICLEA sym, reg 131 1.1 mrg movel a5@(_current_shared_library_a5_offset_), \reg 132 1.1 mrg movel \sym@GOT(\reg), \reg 133 1.1 mrg .endm 134 1.1 mrg 135 1.1 mrg .macro PICPEA sym, areg 136 1.1 mrg movel a5@(_current_shared_library_a5_offset_), \areg 137 1.1 mrg movel \sym@GOT(\areg), sp@- 138 1.1 mrg .endm 139 1.1 mrg 140 1.1 mrg .macro PICCALL addr 141 1.1 mrg PICLEA \addr,a0 142 1.1 mrg jsr a0@ 143 1.1 mrg .endm 144 1.1 mrg 145 1.1 mrg .macro PICJUMP addr 146 1.1 mrg PICLEA \addr,a0 147 1.1 mrg jmp a0@ 148 1.1 mrg .endm 149 1.1 mrg 150 1.1 mrg # else /* !__ID_SHARED_LIBRARY__ */ 151 1.1 mrg 152 1.1 mrg /* Versions for -msep-data */ 153 1.1 mrg 154 1.1 mrg .macro PICLEA sym, reg 155 1.1 mrg movel \sym@GOT(a5), \reg 156 1.1 mrg .endm 157 1.1 mrg 158 1.1 mrg .macro PICPEA sym, areg 159 1.1 mrg movel \sym@GOT(a5), sp@- 160 1.1 mrg .endm 161 1.1 mrg 162 1.1 mrg .macro PICCALL addr 163 1.1 mrg #if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__) 164 1.1 mrg lea \addr-.-8,a0 165 1.1 mrg jsr pc@(a0) 166 1.1 mrg #else 167 1.1 mrg jbsr \addr 168 1.1 mrg #endif 169 1.1 mrg .endm 170 1.1 mrg 171 1.1 mrg .macro PICJUMP addr 172 1.1 mrg /* ISA C has no bra.l instruction, and since this assembly file 173 1.1 mrg gets assembled into multiple object files, we avoid the 174 1.1 mrg bra instruction entirely. */ 175 1.1 mrg #if defined (__mcoldfire__) && !defined (__mcfisab__) 176 1.1 mrg lea \addr-.-8,a0 177 1.1 mrg jmp pc@(a0) 178 1.1 mrg #else 179 1.1 mrg bra \addr 180 1.1 mrg #endif 181 1.1 mrg .endm 182 1.1 mrg 183 1.1 mrg # endif 184 1.1 mrg 185 1.1 mrg # else /* !__uClinux__ */ 186 1.1 mrg 187 1.1 mrg /* Versions for Linux */ 188 1.1 mrg 189 1.1 mrg .macro PICLEA sym, reg 190 1.1 mrg movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \reg 191 1.1 mrg lea (-6, pc, \reg), \reg 192 1.1 mrg movel \sym@GOT(\reg), \reg 193 1.1 mrg .endm 194 1.1 mrg 195 1.1 mrg .macro PICPEA sym, areg 196 1.1 mrg movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \areg 197 1.1 mrg lea (-6, pc, \areg), \areg 198 1.1 mrg movel \sym@GOT(\areg), sp@- 199 1.1 mrg .endm 200 1.1 mrg 201 1.1 mrg .macro PICCALL addr 202 1.1 mrg #if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__) 203 1.1 mrg lea \addr-.-8,a0 204 1.1 mrg jsr pc@(a0) 205 1.1 mrg #else 206 1.2 christos jbsr \addr@PLTPC 207 1.1 mrg #endif 208 1.1 mrg .endm 209 1.1 mrg 210 1.1 mrg .macro PICJUMP addr 211 1.1 mrg /* ISA C has no bra.l instruction, and since this assembly file 212 1.1 mrg gets assembled into multiple object files, we avoid the 213 1.1 mrg bra instruction entirely. */ 214 1.1 mrg #if defined (__mcoldfire__) && !defined (__mcfisab__) 215 1.1 mrg lea \addr-.-8,a0 216 1.1 mrg jmp pc@(a0) 217 1.1 mrg #else 218 1.2 christos bra \addr@PLTPC 219 1.1 mrg #endif 220 1.1 mrg .endm 221 1.1 mrg 222 1.1 mrg # endif 223 1.1 mrg #endif /* __PIC__ */ 224 1.1 mrg 225 1.1 mrg 226 1.1 mrg #ifdef L_floatex 227 1.1 mrg 228 1.1 mrg | This is an attempt at a decent floating point (single, double and 229 1.1 mrg | extended double) code for the GNU C compiler. It should be easy to 230 1.1 mrg | adapt to other compilers (but beware of the local labels!). 231 1.1 mrg 232 1.1 mrg | Starting date: 21 October, 1990 233 1.1 mrg 234 1.1 mrg | It is convenient to introduce the notation (s,e,f) for a floating point 235 1.1 mrg | number, where s=sign, e=exponent, f=fraction. We will call a floating 236 1.1 mrg | point number fpn to abbreviate, independently of the precision. 237 1.1 mrg | Let MAX_EXP be in each case the maximum exponent (255 for floats, 1023 238 1.1 mrg | for doubles and 16383 for long doubles). We then have the following 239 1.1 mrg | different cases: 240 1.1 mrg | 1. Normalized fpns have 0 < e < MAX_EXP. They correspond to 241 1.1 mrg | (-1)^s x 1.f x 2^(e-bias-1). 242 1.1 mrg | 2. Denormalized fpns have e=0. They correspond to numbers of the form 243 1.1 mrg | (-1)^s x 0.f x 2^(-bias). 244 1.1 mrg | 3. +/-INFINITY have e=MAX_EXP, f=0. 245 1.1 mrg | 4. Quiet NaN (Not a Number) have all bits set. 246 1.1 mrg | 5. Signaling NaN (Not a Number) have s=0, e=MAX_EXP, f=1. 247 1.1 mrg 248 1.1 mrg |============================================================================= 249 1.1 mrg | exceptions 250 1.1 mrg |============================================================================= 251 1.1 mrg 252 1.1 mrg | This is the floating point condition code register (_fpCCR): 253 1.1 mrg | 254 1.1 mrg | struct { 255 1.1 mrg | short _exception_bits; 256 1.1 mrg | short _trap_enable_bits; 257 1.1 mrg | short _sticky_bits; 258 1.1 mrg | short _rounding_mode; 259 1.1 mrg | short _format; 260 1.1 mrg | short _last_operation; 261 1.1 mrg | union { 262 1.1 mrg | float sf; 263 1.1 mrg | double df; 264 1.1 mrg | } _operand1; 265 1.1 mrg | union { 266 1.1 mrg | float sf; 267 1.1 mrg | double df; 268 1.1 mrg | } _operand2; 269 1.1 mrg | } _fpCCR; 270 1.1 mrg 271 1.1 mrg .data 272 1.1 mrg .even 273 1.1 mrg 274 1.1 mrg .globl SYM (_fpCCR) 275 1.1 mrg 276 1.1 mrg SYM (_fpCCR): 277 1.1 mrg __exception_bits: 278 1.1 mrg .word 0 279 1.1 mrg __trap_enable_bits: 280 1.1 mrg .word 0 281 1.1 mrg __sticky_bits: 282 1.1 mrg .word 0 283 1.1 mrg __rounding_mode: 284 1.1 mrg .word ROUND_TO_NEAREST 285 1.1 mrg __format: 286 1.1 mrg .word NIL 287 1.1 mrg __last_operation: 288 1.1 mrg .word NOOP 289 1.1 mrg __operand1: 290 1.1 mrg .long 0 291 1.1 mrg .long 0 292 1.1 mrg __operand2: 293 1.1 mrg .long 0 294 1.1 mrg .long 0 295 1.1 mrg 296 1.1 mrg | Offsets: 297 1.1 mrg EBITS = __exception_bits - SYM (_fpCCR) 298 1.1 mrg TRAPE = __trap_enable_bits - SYM (_fpCCR) 299 1.1 mrg STICK = __sticky_bits - SYM (_fpCCR) 300 1.1 mrg ROUND = __rounding_mode - SYM (_fpCCR) 301 1.1 mrg FORMT = __format - SYM (_fpCCR) 302 1.1 mrg LASTO = __last_operation - SYM (_fpCCR) 303 1.1 mrg OPER1 = __operand1 - SYM (_fpCCR) 304 1.1 mrg OPER2 = __operand2 - SYM (_fpCCR) 305 1.1 mrg 306 1.1 mrg | The following exception types are supported: 307 1.1 mrg INEXACT_RESULT = 0x0001 308 1.1 mrg UNDERFLOW = 0x0002 309 1.1 mrg OVERFLOW = 0x0004 310 1.1 mrg DIVIDE_BY_ZERO = 0x0008 311 1.1 mrg INVALID_OPERATION = 0x0010 312 1.1 mrg 313 1.1 mrg | The allowed rounding modes are: 314 1.1 mrg UNKNOWN = -1 315 1.1 mrg ROUND_TO_NEAREST = 0 | round result to nearest representable value 316 1.1 mrg ROUND_TO_ZERO = 1 | round result towards zero 317 1.1 mrg ROUND_TO_PLUS = 2 | round result towards plus infinity 318 1.1 mrg ROUND_TO_MINUS = 3 | round result towards minus infinity 319 1.1 mrg 320 1.1 mrg | The allowed values of format are: 321 1.1 mrg NIL = 0 322 1.1 mrg SINGLE_FLOAT = 1 323 1.1 mrg DOUBLE_FLOAT = 2 324 1.1 mrg LONG_FLOAT = 3 325 1.1 mrg 326 1.1 mrg | The allowed values for the last operation are: 327 1.1 mrg NOOP = 0 328 1.1 mrg ADD = 1 329 1.1 mrg MULTIPLY = 2 330 1.1 mrg DIVIDE = 3 331 1.1 mrg NEGATE = 4 332 1.1 mrg COMPARE = 5 333 1.1 mrg EXTENDSFDF = 6 334 1.1 mrg TRUNCDFSF = 7 335 1.1 mrg 336 1.1 mrg |============================================================================= 337 1.1 mrg | __clear_sticky_bits 338 1.1 mrg |============================================================================= 339 1.1 mrg 340 1.1 mrg | The sticky bits are normally not cleared (thus the name), whereas the 341 1.1 mrg | exception type and exception value reflect the last computation. 342 1.1 mrg | This routine is provided to clear them (you can also write to _fpCCR, 343 1.1 mrg | since it is globally visible). 344 1.1 mrg 345 1.1 mrg .globl SYM (__clear_sticky_bit) 346 1.1 mrg 347 1.1 mrg .text 348 1.1 mrg .even 349 1.1 mrg 350 1.1 mrg | void __clear_sticky_bits(void); 351 1.1 mrg SYM (__clear_sticky_bit): 352 1.1 mrg PICLEA SYM (_fpCCR),a0 353 1.1 mrg #ifndef __mcoldfire__ 354 1.1 mrg movew IMM (0),a0@(STICK) 355 1.1 mrg #else 356 1.1 mrg clr.w a0@(STICK) 357 1.1 mrg #endif 358 1.1 mrg rts 359 1.1 mrg 360 1.1 mrg |============================================================================= 361 1.1 mrg | $_exception_handler 362 1.1 mrg |============================================================================= 363 1.1 mrg 364 1.1 mrg .globl $_exception_handler 365 1.1 mrg 366 1.1 mrg .text 367 1.1 mrg .even 368 1.1 mrg 369 1.1 mrg | This is the common exit point if an exception occurs. 370 1.1 mrg | NOTE: it is NOT callable from C! 371 1.1 mrg | It expects the exception type in d7, the format (SINGLE_FLOAT, 372 1.1 mrg | DOUBLE_FLOAT or LONG_FLOAT) in d6, and the last operation code in d5. 373 1.1 mrg | It sets the corresponding exception and sticky bits, and the format. 374 1.1 mrg | Depending on the format if fills the corresponding slots for the 375 1.1 mrg | operands which produced the exception (all this information is provided 376 1.1 mrg | so if you write your own exception handlers you have enough information 377 1.1 mrg | to deal with the problem). 378 1.1 mrg | Then checks to see if the corresponding exception is trap-enabled, 379 1.1 mrg | in which case it pushes the address of _fpCCR and traps through 380 1.1 mrg | trap FPTRAP (15 for the moment). 381 1.1 mrg 382 1.1 mrg FPTRAP = 15 383 1.1 mrg 384 1.1 mrg $_exception_handler: 385 1.1 mrg PICLEA SYM (_fpCCR),a0 386 1.1 mrg movew d7,a0@(EBITS) | set __exception_bits 387 1.1 mrg #ifndef __mcoldfire__ 388 1.1 mrg orw d7,a0@(STICK) | and __sticky_bits 389 1.1 mrg #else 390 1.1 mrg movew a0@(STICK),d4 391 1.1 mrg orl d7,d4 392 1.1 mrg movew d4,a0@(STICK) 393 1.1 mrg #endif 394 1.1 mrg movew d6,a0@(FORMT) | and __format 395 1.1 mrg movew d5,a0@(LASTO) | and __last_operation 396 1.1 mrg 397 1.1 mrg | Now put the operands in place: 398 1.1 mrg #ifndef __mcoldfire__ 399 1.1 mrg cmpw IMM (SINGLE_FLOAT),d6 400 1.1 mrg #else 401 1.1 mrg cmpl IMM (SINGLE_FLOAT),d6 402 1.1 mrg #endif 403 1.1 mrg beq 1f 404 1.1 mrg movel a6@(8),a0@(OPER1) 405 1.1 mrg movel a6@(12),a0@(OPER1+4) 406 1.1 mrg movel a6@(16),a0@(OPER2) 407 1.1 mrg movel a6@(20),a0@(OPER2+4) 408 1.1 mrg bra 2f 409 1.1 mrg 1: movel a6@(8),a0@(OPER1) 410 1.1 mrg movel a6@(12),a0@(OPER2) 411 1.1 mrg 2: 412 1.1 mrg | And check whether the exception is trap-enabled: 413 1.1 mrg #ifndef __mcoldfire__ 414 1.1 mrg andw a0@(TRAPE),d7 | is exception trap-enabled? 415 1.1 mrg #else 416 1.1 mrg clrl d6 417 1.1 mrg movew a0@(TRAPE),d6 418 1.1 mrg andl d6,d7 419 1.1 mrg #endif 420 1.1 mrg beq 1f | no, exit 421 1.1 mrg PICPEA SYM (_fpCCR),a1 | yes, push address of _fpCCR 422 1.1 mrg trap IMM (FPTRAP) | and trap 423 1.1 mrg #ifndef __mcoldfire__ 424 1.1 mrg 1: moveml sp@+,d2-d7 | restore data registers 425 1.1 mrg #else 426 1.1 mrg 1: moveml sp@,d2-d7 427 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 428 1.1 mrg | be adjusted here. 429 1.1 mrg #endif 430 1.1 mrg unlk a6 | and return 431 1.1 mrg rts 432 1.1 mrg #endif /* L_floatex */ 433 1.1 mrg 434 1.1 mrg #ifdef L_mulsi3 435 1.1 mrg .text 436 1.1 mrg FUNC(__mulsi3) 437 1.1 mrg .globl SYM (__mulsi3) 438 1.11 mrg .globl SYM (__mulsi3_internal) 439 1.11 mrg .hidden SYM (__mulsi3_internal) 440 1.1 mrg SYM (__mulsi3): 441 1.11 mrg SYM (__mulsi3_internal): 442 1.1 mrg movew sp@(4), d0 /* x0 -> d0 */ 443 1.1 mrg muluw sp@(10), d0 /* x0*y1 */ 444 1.1 mrg movew sp@(6), d1 /* x1 -> d1 */ 445 1.1 mrg muluw sp@(8), d1 /* x1*y0 */ 446 1.1 mrg #ifndef __mcoldfire__ 447 1.1 mrg addw d1, d0 448 1.1 mrg #else 449 1.1 mrg addl d1, d0 450 1.1 mrg #endif 451 1.1 mrg swap d0 452 1.1 mrg clrw d0 453 1.1 mrg movew sp@(6), d1 /* x1 -> d1 */ 454 1.1 mrg muluw sp@(10), d1 /* x1*y1 */ 455 1.1 mrg addl d1, d0 456 1.1 mrg 457 1.1 mrg rts 458 1.1 mrg #endif /* L_mulsi3 */ 459 1.1 mrg 460 1.1 mrg #ifdef L_udivsi3 461 1.1 mrg .text 462 1.1 mrg FUNC(__udivsi3) 463 1.1 mrg .globl SYM (__udivsi3) 464 1.11 mrg .globl SYM (__udivsi3_internal) 465 1.11 mrg .hidden SYM (__udivsi3_internal) 466 1.1 mrg SYM (__udivsi3): 467 1.11 mrg SYM (__udivsi3_internal): 468 1.1 mrg #ifndef __mcoldfire__ 469 1.1 mrg movel d2, sp@- 470 1.1 mrg movel sp@(12), d1 /* d1 = divisor */ 471 1.1 mrg movel sp@(8), d0 /* d0 = dividend */ 472 1.1 mrg 473 1.1 mrg cmpl IMM (0x10000), d1 /* divisor >= 2 ^ 16 ? */ 474 1.1 mrg jcc L3 /* then try next algorithm */ 475 1.1 mrg movel d0, d2 476 1.1 mrg clrw d2 477 1.1 mrg swap d2 478 1.1 mrg divu d1, d2 /* high quotient in lower word */ 479 1.1 mrg movew d2, d0 /* save high quotient */ 480 1.1 mrg swap d0 481 1.1 mrg movew sp@(10), d2 /* get low dividend + high rest */ 482 1.1 mrg divu d1, d2 /* low quotient */ 483 1.1 mrg movew d2, d0 484 1.1 mrg jra L6 485 1.1 mrg 486 1.1 mrg L3: movel d1, d2 /* use d2 as divisor backup */ 487 1.1 mrg L4: lsrl IMM (1), d1 /* shift divisor */ 488 1.1 mrg lsrl IMM (1), d0 /* shift dividend */ 489 1.1 mrg cmpl IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ? */ 490 1.1 mrg jcc L4 491 1.1 mrg divu d1, d0 /* now we have 16-bit divisor */ 492 1.1 mrg andl IMM (0xffff), d0 /* mask out divisor, ignore remainder */ 493 1.1 mrg 494 1.1 mrg /* Multiply the 16-bit tentative quotient with the 32-bit divisor. Because of 495 1.1 mrg the operand ranges, this might give a 33-bit product. If this product is 496 1.1 mrg greater than the dividend, the tentative quotient was too large. */ 497 1.1 mrg movel d2, d1 498 1.1 mrg mulu d0, d1 /* low part, 32 bits */ 499 1.1 mrg swap d2 500 1.1 mrg mulu d0, d2 /* high part, at most 17 bits */ 501 1.1 mrg swap d2 /* align high part with low part */ 502 1.1 mrg tstw d2 /* high part 17 bits? */ 503 1.1 mrg jne L5 /* if 17 bits, quotient was too large */ 504 1.1 mrg addl d2, d1 /* add parts */ 505 1.1 mrg jcs L5 /* if sum is 33 bits, quotient was too large */ 506 1.1 mrg cmpl sp@(8), d1 /* compare the sum with the dividend */ 507 1.1 mrg jls L6 /* if sum > dividend, quotient was too large */ 508 1.1 mrg L5: subql IMM (1), d0 /* adjust quotient */ 509 1.1 mrg 510 1.1 mrg L6: movel sp@+, d2 511 1.1 mrg rts 512 1.1 mrg 513 1.1 mrg #else /* __mcoldfire__ */ 514 1.1 mrg 515 1.1 mrg /* ColdFire implementation of non-restoring division algorithm from 516 1.1 mrg Hennessy & Patterson, Appendix A. */ 517 1.1 mrg link a6,IMM (-12) 518 1.1 mrg moveml d2-d4,sp@ 519 1.1 mrg movel a6@(8),d0 520 1.1 mrg movel a6@(12),d1 521 1.1 mrg clrl d2 | clear p 522 1.1 mrg moveq IMM (31),d4 523 1.1 mrg L1: addl d0,d0 | shift reg pair (p,a) one bit left 524 1.1 mrg addxl d2,d2 525 1.1 mrg movl d2,d3 | subtract b from p, store in tmp. 526 1.1 mrg subl d1,d3 527 1.1 mrg jcs L2 | if no carry, 528 1.1 mrg bset IMM (0),d0 | set the low order bit of a to 1, 529 1.1 mrg movl d3,d2 | and store tmp in p. 530 1.1 mrg L2: subql IMM (1),d4 531 1.1 mrg jcc L1 532 1.1 mrg moveml sp@,d2-d4 | restore data registers 533 1.1 mrg unlk a6 | and return 534 1.1 mrg rts 535 1.1 mrg #endif /* __mcoldfire__ */ 536 1.1 mrg 537 1.1 mrg #endif /* L_udivsi3 */ 538 1.1 mrg 539 1.1 mrg #ifdef L_divsi3 540 1.1 mrg .text 541 1.1 mrg FUNC(__divsi3) 542 1.1 mrg .globl SYM (__divsi3) 543 1.11 mrg .globl SYM (__divsi3_internal) 544 1.11 mrg .hidden SYM (__divsi3_internal) 545 1.1 mrg SYM (__divsi3): 546 1.11 mrg SYM (__divsi3_internal): 547 1.1 mrg movel d2, sp@- 548 1.1 mrg 549 1.1 mrg moveq IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */ 550 1.1 mrg movel sp@(12), d1 /* d1 = divisor */ 551 1.1 mrg jpl L1 552 1.1 mrg negl d1 553 1.1 mrg #ifndef __mcoldfire__ 554 1.1 mrg negb d2 /* change sign because divisor <0 */ 555 1.1 mrg #else 556 1.1 mrg negl d2 /* change sign because divisor <0 */ 557 1.1 mrg #endif 558 1.1 mrg L1: movel sp@(8), d0 /* d0 = dividend */ 559 1.1 mrg jpl L2 560 1.1 mrg negl d0 561 1.1 mrg #ifndef __mcoldfire__ 562 1.1 mrg negb d2 563 1.1 mrg #else 564 1.1 mrg negl d2 565 1.1 mrg #endif 566 1.1 mrg 567 1.1 mrg L2: movel d1, sp@- 568 1.1 mrg movel d0, sp@- 569 1.11 mrg PICCALL SYM (__udivsi3_internal) /* divide abs(dividend) by abs(divisor) */ 570 1.1 mrg addql IMM (8), sp 571 1.1 mrg 572 1.1 mrg tstb d2 573 1.1 mrg jpl L3 574 1.1 mrg negl d0 575 1.1 mrg 576 1.1 mrg L3: movel sp@+, d2 577 1.1 mrg rts 578 1.1 mrg #endif /* L_divsi3 */ 579 1.1 mrg 580 1.1 mrg #ifdef L_umodsi3 581 1.1 mrg .text 582 1.1 mrg FUNC(__umodsi3) 583 1.1 mrg .globl SYM (__umodsi3) 584 1.1 mrg SYM (__umodsi3): 585 1.1 mrg movel sp@(8), d1 /* d1 = divisor */ 586 1.1 mrg movel sp@(4), d0 /* d0 = dividend */ 587 1.1 mrg movel d1, sp@- 588 1.1 mrg movel d0, sp@- 589 1.11 mrg PICCALL SYM (__udivsi3_internal) 590 1.1 mrg addql IMM (8), sp 591 1.1 mrg movel sp@(8), d1 /* d1 = divisor */ 592 1.1 mrg #ifndef __mcoldfire__ 593 1.1 mrg movel d1, sp@- 594 1.1 mrg movel d0, sp@- 595 1.11 mrg PICCALL SYM (__mulsi3_internal) /* d0 = (a/b)*b */ 596 1.1 mrg addql IMM (8), sp 597 1.1 mrg #else 598 1.1 mrg mulsl d1,d0 599 1.1 mrg #endif 600 1.1 mrg movel sp@(4), d1 /* d1 = dividend */ 601 1.1 mrg subl d0, d1 /* d1 = a - (a/b)*b */ 602 1.1 mrg movel d1, d0 603 1.1 mrg rts 604 1.1 mrg #endif /* L_umodsi3 */ 605 1.1 mrg 606 1.1 mrg #ifdef L_modsi3 607 1.1 mrg .text 608 1.1 mrg FUNC(__modsi3) 609 1.1 mrg .globl SYM (__modsi3) 610 1.1 mrg SYM (__modsi3): 611 1.1 mrg movel sp@(8), d1 /* d1 = divisor */ 612 1.1 mrg movel sp@(4), d0 /* d0 = dividend */ 613 1.1 mrg movel d1, sp@- 614 1.1 mrg movel d0, sp@- 615 1.11 mrg PICCALL SYM (__divsi3_internal) 616 1.1 mrg addql IMM (8), sp 617 1.1 mrg movel sp@(8), d1 /* d1 = divisor */ 618 1.1 mrg #ifndef __mcoldfire__ 619 1.1 mrg movel d1, sp@- 620 1.1 mrg movel d0, sp@- 621 1.11 mrg PICCALL SYM (__mulsi3_internal) /* d0 = (a/b)*b */ 622 1.1 mrg addql IMM (8), sp 623 1.1 mrg #else 624 1.1 mrg mulsl d1,d0 625 1.1 mrg #endif 626 1.1 mrg movel sp@(4), d1 /* d1 = dividend */ 627 1.1 mrg subl d0, d1 /* d1 = a - (a/b)*b */ 628 1.1 mrg movel d1, d0 629 1.1 mrg rts 630 1.1 mrg #endif /* L_modsi3 */ 631 1.1 mrg 632 1.1 mrg 633 1.1 mrg #ifdef L_double 634 1.1 mrg 635 1.1 mrg .globl SYM (_fpCCR) 636 1.1 mrg .globl $_exception_handler 637 1.1 mrg 638 1.1 mrg QUIET_NaN = 0xffffffff 639 1.1 mrg 640 1.1 mrg D_MAX_EXP = 0x07ff 641 1.1 mrg D_BIAS = 1022 642 1.1 mrg DBL_MAX_EXP = D_MAX_EXP - D_BIAS 643 1.1 mrg DBL_MIN_EXP = 1 - D_BIAS 644 1.1 mrg DBL_MANT_DIG = 53 645 1.1 mrg 646 1.1 mrg INEXACT_RESULT = 0x0001 647 1.1 mrg UNDERFLOW = 0x0002 648 1.1 mrg OVERFLOW = 0x0004 649 1.1 mrg DIVIDE_BY_ZERO = 0x0008 650 1.1 mrg INVALID_OPERATION = 0x0010 651 1.1 mrg 652 1.1 mrg DOUBLE_FLOAT = 2 653 1.1 mrg 654 1.1 mrg NOOP = 0 655 1.1 mrg ADD = 1 656 1.1 mrg MULTIPLY = 2 657 1.1 mrg DIVIDE = 3 658 1.1 mrg NEGATE = 4 659 1.1 mrg COMPARE = 5 660 1.1 mrg EXTENDSFDF = 6 661 1.1 mrg TRUNCDFSF = 7 662 1.1 mrg 663 1.1 mrg UNKNOWN = -1 664 1.1 mrg ROUND_TO_NEAREST = 0 | round result to nearest representable value 665 1.1 mrg ROUND_TO_ZERO = 1 | round result towards zero 666 1.1 mrg ROUND_TO_PLUS = 2 | round result towards plus infinity 667 1.1 mrg ROUND_TO_MINUS = 3 | round result towards minus infinity 668 1.1 mrg 669 1.1 mrg | Entry points: 670 1.1 mrg 671 1.1 mrg .globl SYM (__adddf3) 672 1.1 mrg .globl SYM (__subdf3) 673 1.1 mrg .globl SYM (__muldf3) 674 1.1 mrg .globl SYM (__divdf3) 675 1.1 mrg .globl SYM (__negdf2) 676 1.1 mrg .globl SYM (__cmpdf2) 677 1.1 mrg .globl SYM (__cmpdf2_internal) 678 1.1 mrg .hidden SYM (__cmpdf2_internal) 679 1.1 mrg 680 1.1 mrg .text 681 1.1 mrg .even 682 1.1 mrg 683 1.1 mrg | These are common routines to return and signal exceptions. 684 1.1 mrg 685 1.1 mrg Ld$den: 686 1.1 mrg | Return and signal a denormalized number 687 1.1 mrg orl d7,d0 688 1.1 mrg movew IMM (INEXACT_RESULT+UNDERFLOW),d7 689 1.1 mrg moveq IMM (DOUBLE_FLOAT),d6 690 1.1 mrg PICJUMP $_exception_handler 691 1.1 mrg 692 1.1 mrg Ld$infty: 693 1.1 mrg Ld$overflow: 694 1.1 mrg | Return a properly signed INFINITY and set the exception flags 695 1.1 mrg movel IMM (0x7ff00000),d0 696 1.1 mrg movel IMM (0),d1 697 1.1 mrg orl d7,d0 698 1.1 mrg movew IMM (INEXACT_RESULT+OVERFLOW),d7 699 1.1 mrg moveq IMM (DOUBLE_FLOAT),d6 700 1.1 mrg PICJUMP $_exception_handler 701 1.1 mrg 702 1.1 mrg Ld$underflow: 703 1.1 mrg | Return 0 and set the exception flags 704 1.1 mrg movel IMM (0),d0 705 1.1 mrg movel d0,d1 706 1.1 mrg movew IMM (INEXACT_RESULT+UNDERFLOW),d7 707 1.1 mrg moveq IMM (DOUBLE_FLOAT),d6 708 1.1 mrg PICJUMP $_exception_handler 709 1.1 mrg 710 1.1 mrg Ld$inop: 711 1.1 mrg | Return a quiet NaN and set the exception flags 712 1.1 mrg movel IMM (QUIET_NaN),d0 713 1.1 mrg movel d0,d1 714 1.1 mrg movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7 715 1.1 mrg moveq IMM (DOUBLE_FLOAT),d6 716 1.1 mrg PICJUMP $_exception_handler 717 1.1 mrg 718 1.1 mrg Ld$div$0: 719 1.1 mrg | Return a properly signed INFINITY and set the exception flags 720 1.1 mrg movel IMM (0x7ff00000),d0 721 1.1 mrg movel IMM (0),d1 722 1.1 mrg orl d7,d0 723 1.1 mrg movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7 724 1.1 mrg moveq IMM (DOUBLE_FLOAT),d6 725 1.1 mrg PICJUMP $_exception_handler 726 1.1 mrg 727 1.1 mrg |============================================================================= 728 1.1 mrg |============================================================================= 729 1.1 mrg | double precision routines 730 1.1 mrg |============================================================================= 731 1.1 mrg |============================================================================= 732 1.1 mrg 733 1.1 mrg | A double precision floating point number (double) has the format: 734 1.1 mrg | 735 1.1 mrg | struct _double { 736 1.1 mrg | unsigned int sign : 1; /* sign bit */ 737 1.1 mrg | unsigned int exponent : 11; /* exponent, shifted by 126 */ 738 1.1 mrg | unsigned int fraction : 52; /* fraction */ 739 1.1 mrg | } double; 740 1.1 mrg | 741 1.1 mrg | Thus sizeof(double) = 8 (64 bits). 742 1.1 mrg | 743 1.1 mrg | All the routines are callable from C programs, and return the result 744 1.1 mrg | in the register pair d0-d1. They also preserve all registers except 745 1.1 mrg | d0-d1 and a0-a1. 746 1.1 mrg 747 1.1 mrg |============================================================================= 748 1.1 mrg | __subdf3 749 1.1 mrg |============================================================================= 750 1.1 mrg 751 1.1 mrg | double __subdf3(double, double); 752 1.1 mrg FUNC(__subdf3) 753 1.1 mrg SYM (__subdf3): 754 1.1 mrg bchg IMM (31),sp@(12) | change sign of second operand 755 1.1 mrg | and fall through, so we always add 756 1.1 mrg |============================================================================= 757 1.1 mrg | __adddf3 758 1.1 mrg |============================================================================= 759 1.1 mrg 760 1.1 mrg | double __adddf3(double, double); 761 1.1 mrg FUNC(__adddf3) 762 1.1 mrg SYM (__adddf3): 763 1.1 mrg #ifndef __mcoldfire__ 764 1.1 mrg link a6,IMM (0) | everything will be done in registers 765 1.1 mrg moveml d2-d7,sp@- | save all data registers and a2 (but d0-d1) 766 1.1 mrg #else 767 1.1 mrg link a6,IMM (-24) 768 1.1 mrg moveml d2-d7,sp@ 769 1.1 mrg #endif 770 1.1 mrg movel a6@(8),d0 | get first operand 771 1.1 mrg movel a6@(12),d1 | 772 1.1 mrg movel a6@(16),d2 | get second operand 773 1.1 mrg movel a6@(20),d3 | 774 1.1 mrg 775 1.1 mrg movel d0,d7 | get d0's sign bit in d7 ' 776 1.1 mrg addl d1,d1 | check and clear sign bit of a, and gain one 777 1.1 mrg addxl d0,d0 | bit of extra precision 778 1.1 mrg beq Ladddf$b | if zero return second operand 779 1.1 mrg 780 1.1 mrg movel d2,d6 | save sign in d6 781 1.1 mrg addl d3,d3 | get rid of sign bit and gain one bit of 782 1.1 mrg addxl d2,d2 | extra precision 783 1.1 mrg beq Ladddf$a | if zero return first operand 784 1.1 mrg 785 1.1 mrg andl IMM (0x80000000),d7 | isolate a's sign bit ' 786 1.1 mrg swap d6 | and also b's sign bit ' 787 1.1 mrg #ifndef __mcoldfire__ 788 1.1 mrg andw IMM (0x8000),d6 | 789 1.1 mrg orw d6,d7 | and combine them into d7, so that a's sign ' 790 1.1 mrg | bit is in the high word and b's is in the ' 791 1.1 mrg | low word, so d6 is free to be used 792 1.1 mrg #else 793 1.1 mrg andl IMM (0x8000),d6 794 1.1 mrg orl d6,d7 795 1.1 mrg #endif 796 1.1 mrg movel d7,a0 | now save d7 into a0, so d7 is free to 797 1.1 mrg | be used also 798 1.1 mrg 799 1.1 mrg | Get the exponents and check for denormalized and/or infinity. 800 1.1 mrg 801 1.1 mrg movel IMM (0x001fffff),d6 | mask for the fraction 802 1.1 mrg movel IMM (0x00200000),d7 | mask to put hidden bit back 803 1.1 mrg 804 1.1 mrg movel d0,d4 | 805 1.1 mrg andl d6,d0 | get fraction in d0 806 1.1 mrg notl d6 | make d6 into mask for the exponent 807 1.1 mrg andl d6,d4 | get exponent in d4 808 1.1 mrg beq Ladddf$a$den | branch if a is denormalized 809 1.1 mrg cmpl d6,d4 | check for INFINITY or NaN 810 1.1 mrg beq Ladddf$nf | 811 1.1 mrg orl d7,d0 | and put hidden bit back 812 1.1 mrg Ladddf$1: 813 1.1 mrg swap d4 | shift right exponent so that it starts 814 1.1 mrg #ifndef __mcoldfire__ 815 1.1 mrg lsrw IMM (5),d4 | in bit 0 and not bit 20 816 1.1 mrg #else 817 1.1 mrg lsrl IMM (5),d4 | in bit 0 and not bit 20 818 1.1 mrg #endif 819 1.1 mrg | Now we have a's exponent in d4 and fraction in d0-d1 ' 820 1.1 mrg movel d2,d5 | save b to get exponent 821 1.1 mrg andl d6,d5 | get exponent in d5 822 1.1 mrg beq Ladddf$b$den | branch if b is denormalized 823 1.1 mrg cmpl d6,d5 | check for INFINITY or NaN 824 1.1 mrg beq Ladddf$nf 825 1.1 mrg notl d6 | make d6 into mask for the fraction again 826 1.1 mrg andl d6,d2 | and get fraction in d2 827 1.1 mrg orl d7,d2 | and put hidden bit back 828 1.1 mrg Ladddf$2: 829 1.1 mrg swap d5 | shift right exponent so that it starts 830 1.1 mrg #ifndef __mcoldfire__ 831 1.1 mrg lsrw IMM (5),d5 | in bit 0 and not bit 20 832 1.1 mrg #else 833 1.1 mrg lsrl IMM (5),d5 | in bit 0 and not bit 20 834 1.1 mrg #endif 835 1.1 mrg 836 1.1 mrg | Now we have b's exponent in d5 and fraction in d2-d3. ' 837 1.1 mrg 838 1.1 mrg | The situation now is as follows: the signs are combined in a0, the 839 1.1 mrg | numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a) 840 1.1 mrg | and d5 (b). To do the rounding correctly we need to keep all the 841 1.1 mrg | bits until the end, so we need to use d0-d1-d2-d3 for the first number 842 1.1 mrg | and d4-d5-d6-d7 for the second. To do this we store (temporarily) the 843 1.1 mrg | exponents in a2-a3. 844 1.1 mrg 845 1.1 mrg #ifndef __mcoldfire__ 846 1.1 mrg moveml a2-a3,sp@- | save the address registers 847 1.1 mrg #else 848 1.1 mrg movel a2,sp@- 849 1.1 mrg movel a3,sp@- 850 1.1 mrg movel a4,sp@- 851 1.1 mrg #endif 852 1.1 mrg 853 1.1 mrg movel d4,a2 | save the exponents 854 1.1 mrg movel d5,a3 | 855 1.1 mrg 856 1.1 mrg movel IMM (0),d7 | and move the numbers around 857 1.1 mrg movel d7,d6 | 858 1.1 mrg movel d3,d5 | 859 1.1 mrg movel d2,d4 | 860 1.1 mrg movel d7,d3 | 861 1.1 mrg movel d7,d2 | 862 1.1 mrg 863 1.1 mrg | Here we shift the numbers until the exponents are the same, and put 864 1.1 mrg | the largest exponent in a2. 865 1.1 mrg #ifndef __mcoldfire__ 866 1.1 mrg exg d4,a2 | get exponents back 867 1.1 mrg exg d5,a3 | 868 1.1 mrg cmpw d4,d5 | compare the exponents 869 1.1 mrg #else 870 1.1 mrg movel d4,a4 | get exponents back 871 1.1 mrg movel a2,d4 872 1.1 mrg movel a4,a2 873 1.1 mrg movel d5,a4 874 1.1 mrg movel a3,d5 875 1.1 mrg movel a4,a3 876 1.1 mrg cmpl d4,d5 | compare the exponents 877 1.1 mrg #endif 878 1.1 mrg beq Ladddf$3 | if equal don't shift ' 879 1.1 mrg bhi 9f | branch if second exponent is higher 880 1.1 mrg 881 1.1 mrg | Here we have a's exponent larger than b's, so we have to shift b. We do 882 1.1 mrg | this by using as counter d2: 883 1.1 mrg 1: movew d4,d2 | move largest exponent to d2 884 1.1 mrg #ifndef __mcoldfire__ 885 1.1 mrg subw d5,d2 | and subtract second exponent 886 1.1 mrg exg d4,a2 | get back the longs we saved 887 1.1 mrg exg d5,a3 | 888 1.1 mrg #else 889 1.1 mrg subl d5,d2 | and subtract second exponent 890 1.1 mrg movel d4,a4 | get back the longs we saved 891 1.1 mrg movel a2,d4 892 1.1 mrg movel a4,a2 893 1.1 mrg movel d5,a4 894 1.1 mrg movel a3,d5 895 1.1 mrg movel a4,a3 896 1.1 mrg #endif 897 1.1 mrg | if difference is too large we don't shift (actually, we can just exit) ' 898 1.1 mrg #ifndef __mcoldfire__ 899 1.1 mrg cmpw IMM (DBL_MANT_DIG+2),d2 900 1.1 mrg #else 901 1.1 mrg cmpl IMM (DBL_MANT_DIG+2),d2 902 1.1 mrg #endif 903 1.1 mrg bge Ladddf$b$small 904 1.1 mrg #ifndef __mcoldfire__ 905 1.1 mrg cmpw IMM (32),d2 | if difference >= 32, shift by longs 906 1.1 mrg #else 907 1.1 mrg cmpl IMM (32),d2 | if difference >= 32, shift by longs 908 1.1 mrg #endif 909 1.1 mrg bge 5f 910 1.1 mrg 2: 911 1.1 mrg #ifndef __mcoldfire__ 912 1.1 mrg cmpw IMM (16),d2 | if difference >= 16, shift by words 913 1.1 mrg #else 914 1.1 mrg cmpl IMM (16),d2 | if difference >= 16, shift by words 915 1.1 mrg #endif 916 1.1 mrg bge 6f 917 1.1 mrg bra 3f | enter dbra loop 918 1.1 mrg 919 1.1 mrg 4: 920 1.1 mrg #ifndef __mcoldfire__ 921 1.1 mrg lsrl IMM (1),d4 922 1.1 mrg roxrl IMM (1),d5 923 1.1 mrg roxrl IMM (1),d6 924 1.1 mrg roxrl IMM (1),d7 925 1.1 mrg #else 926 1.1 mrg lsrl IMM (1),d7 927 1.1 mrg btst IMM (0),d6 928 1.1 mrg beq 10f 929 1.1 mrg bset IMM (31),d7 930 1.1 mrg 10: lsrl IMM (1),d6 931 1.1 mrg btst IMM (0),d5 932 1.1 mrg beq 11f 933 1.1 mrg bset IMM (31),d6 934 1.1 mrg 11: lsrl IMM (1),d5 935 1.1 mrg btst IMM (0),d4 936 1.1 mrg beq 12f 937 1.1 mrg bset IMM (31),d5 938 1.1 mrg 12: lsrl IMM (1),d4 939 1.1 mrg #endif 940 1.1 mrg 3: 941 1.1 mrg #ifndef __mcoldfire__ 942 1.1 mrg dbra d2,4b 943 1.1 mrg #else 944 1.1 mrg subql IMM (1),d2 945 1.1 mrg bpl 4b 946 1.1 mrg #endif 947 1.1 mrg movel IMM (0),d2 948 1.1 mrg movel d2,d3 949 1.1 mrg bra Ladddf$4 950 1.1 mrg 5: 951 1.1 mrg movel d6,d7 952 1.1 mrg movel d5,d6 953 1.1 mrg movel d4,d5 954 1.1 mrg movel IMM (0),d4 955 1.1 mrg #ifndef __mcoldfire__ 956 1.1 mrg subw IMM (32),d2 957 1.1 mrg #else 958 1.1 mrg subl IMM (32),d2 959 1.1 mrg #endif 960 1.1 mrg bra 2b 961 1.1 mrg 6: 962 1.1 mrg movew d6,d7 963 1.1 mrg swap d7 964 1.1 mrg movew d5,d6 965 1.1 mrg swap d6 966 1.1 mrg movew d4,d5 967 1.1 mrg swap d5 968 1.1 mrg movew IMM (0),d4 969 1.1 mrg swap d4 970 1.1 mrg #ifndef __mcoldfire__ 971 1.1 mrg subw IMM (16),d2 972 1.1 mrg #else 973 1.1 mrg subl IMM (16),d2 974 1.1 mrg #endif 975 1.1 mrg bra 3b 976 1.1 mrg 977 1.1 mrg 9: 978 1.1 mrg #ifndef __mcoldfire__ 979 1.1 mrg exg d4,d5 980 1.1 mrg movew d4,d6 981 1.1 mrg subw d5,d6 | keep d5 (largest exponent) in d4 982 1.1 mrg exg d4,a2 983 1.1 mrg exg d5,a3 984 1.1 mrg #else 985 1.1 mrg movel d5,d6 986 1.1 mrg movel d4,d5 987 1.1 mrg movel d6,d4 988 1.1 mrg subl d5,d6 989 1.1 mrg movel d4,a4 990 1.1 mrg movel a2,d4 991 1.1 mrg movel a4,a2 992 1.1 mrg movel d5,a4 993 1.1 mrg movel a3,d5 994 1.1 mrg movel a4,a3 995 1.1 mrg #endif 996 1.1 mrg | if difference is too large we don't shift (actually, we can just exit) ' 997 1.1 mrg #ifndef __mcoldfire__ 998 1.1 mrg cmpw IMM (DBL_MANT_DIG+2),d6 999 1.1 mrg #else 1000 1.1 mrg cmpl IMM (DBL_MANT_DIG+2),d6 1001 1.1 mrg #endif 1002 1.1 mrg bge Ladddf$a$small 1003 1.1 mrg #ifndef __mcoldfire__ 1004 1.1 mrg cmpw IMM (32),d6 | if difference >= 32, shift by longs 1005 1.1 mrg #else 1006 1.1 mrg cmpl IMM (32),d6 | if difference >= 32, shift by longs 1007 1.1 mrg #endif 1008 1.1 mrg bge 5f 1009 1.1 mrg 2: 1010 1.1 mrg #ifndef __mcoldfire__ 1011 1.1 mrg cmpw IMM (16),d6 | if difference >= 16, shift by words 1012 1.1 mrg #else 1013 1.1 mrg cmpl IMM (16),d6 | if difference >= 16, shift by words 1014 1.1 mrg #endif 1015 1.1 mrg bge 6f 1016 1.1 mrg bra 3f | enter dbra loop 1017 1.1 mrg 1018 1.1 mrg 4: 1019 1.1 mrg #ifndef __mcoldfire__ 1020 1.1 mrg lsrl IMM (1),d0 1021 1.1 mrg roxrl IMM (1),d1 1022 1.1 mrg roxrl IMM (1),d2 1023 1.1 mrg roxrl IMM (1),d3 1024 1.1 mrg #else 1025 1.1 mrg lsrl IMM (1),d3 1026 1.1 mrg btst IMM (0),d2 1027 1.1 mrg beq 10f 1028 1.1 mrg bset IMM (31),d3 1029 1.1 mrg 10: lsrl IMM (1),d2 1030 1.1 mrg btst IMM (0),d1 1031 1.1 mrg beq 11f 1032 1.1 mrg bset IMM (31),d2 1033 1.1 mrg 11: lsrl IMM (1),d1 1034 1.1 mrg btst IMM (0),d0 1035 1.1 mrg beq 12f 1036 1.1 mrg bset IMM (31),d1 1037 1.1 mrg 12: lsrl IMM (1),d0 1038 1.1 mrg #endif 1039 1.1 mrg 3: 1040 1.1 mrg #ifndef __mcoldfire__ 1041 1.1 mrg dbra d6,4b 1042 1.1 mrg #else 1043 1.1 mrg subql IMM (1),d6 1044 1.1 mrg bpl 4b 1045 1.1 mrg #endif 1046 1.1 mrg movel IMM (0),d7 1047 1.1 mrg movel d7,d6 1048 1.1 mrg bra Ladddf$4 1049 1.1 mrg 5: 1050 1.1 mrg movel d2,d3 1051 1.1 mrg movel d1,d2 1052 1.1 mrg movel d0,d1 1053 1.1 mrg movel IMM (0),d0 1054 1.1 mrg #ifndef __mcoldfire__ 1055 1.1 mrg subw IMM (32),d6 1056 1.1 mrg #else 1057 1.1 mrg subl IMM (32),d6 1058 1.1 mrg #endif 1059 1.1 mrg bra 2b 1060 1.1 mrg 6: 1061 1.1 mrg movew d2,d3 1062 1.1 mrg swap d3 1063 1.1 mrg movew d1,d2 1064 1.1 mrg swap d2 1065 1.1 mrg movew d0,d1 1066 1.1 mrg swap d1 1067 1.1 mrg movew IMM (0),d0 1068 1.1 mrg swap d0 1069 1.1 mrg #ifndef __mcoldfire__ 1070 1.1 mrg subw IMM (16),d6 1071 1.1 mrg #else 1072 1.1 mrg subl IMM (16),d6 1073 1.1 mrg #endif 1074 1.1 mrg bra 3b 1075 1.1 mrg Ladddf$3: 1076 1.1 mrg #ifndef __mcoldfire__ 1077 1.1 mrg exg d4,a2 1078 1.1 mrg exg d5,a3 1079 1.1 mrg #else 1080 1.1 mrg movel d4,a4 1081 1.1 mrg movel a2,d4 1082 1.1 mrg movel a4,a2 1083 1.1 mrg movel d5,a4 1084 1.1 mrg movel a3,d5 1085 1.1 mrg movel a4,a3 1086 1.1 mrg #endif 1087 1.1 mrg Ladddf$4: 1088 1.1 mrg | Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and 1089 1.1 mrg | the signs in a4. 1090 1.1 mrg 1091 1.1 mrg | Here we have to decide whether to add or subtract the numbers: 1092 1.1 mrg #ifndef __mcoldfire__ 1093 1.1 mrg exg d7,a0 | get the signs 1094 1.1 mrg exg d6,a3 | a3 is free to be used 1095 1.1 mrg #else 1096 1.1 mrg movel d7,a4 1097 1.1 mrg movel a0,d7 1098 1.1 mrg movel a4,a0 1099 1.1 mrg movel d6,a4 1100 1.1 mrg movel a3,d6 1101 1.1 mrg movel a4,a3 1102 1.1 mrg #endif 1103 1.1 mrg movel d7,d6 | 1104 1.1 mrg movew IMM (0),d7 | get a's sign in d7 ' 1105 1.1 mrg swap d6 | 1106 1.1 mrg movew IMM (0),d6 | and b's sign in d6 ' 1107 1.1 mrg eorl d7,d6 | compare the signs 1108 1.1 mrg bmi Lsubdf$0 | if the signs are different we have 1109 1.1 mrg | to subtract 1110 1.1 mrg #ifndef __mcoldfire__ 1111 1.1 mrg exg d7,a0 | else we add the numbers 1112 1.1 mrg exg d6,a3 | 1113 1.1 mrg #else 1114 1.1 mrg movel d7,a4 1115 1.1 mrg movel a0,d7 1116 1.1 mrg movel a4,a0 1117 1.1 mrg movel d6,a4 1118 1.1 mrg movel a3,d6 1119 1.1 mrg movel a4,a3 1120 1.1 mrg #endif 1121 1.1 mrg addl d7,d3 | 1122 1.1 mrg addxl d6,d2 | 1123 1.1 mrg addxl d5,d1 | 1124 1.1 mrg addxl d4,d0 | 1125 1.1 mrg 1126 1.1 mrg movel a2,d4 | return exponent to d4 1127 1.1 mrg movel a0,d7 | 1128 1.1 mrg andl IMM (0x80000000),d7 | d7 now has the sign 1129 1.1 mrg 1130 1.1 mrg #ifndef __mcoldfire__ 1131 1.1 mrg moveml sp@+,a2-a3 1132 1.1 mrg #else 1133 1.1 mrg movel sp@+,a4 1134 1.1 mrg movel sp@+,a3 1135 1.1 mrg movel sp@+,a2 1136 1.1 mrg #endif 1137 1.1 mrg 1138 1.1 mrg | Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider 1139 1.1 mrg | the case of denormalized numbers in the rounding routine itself). 1140 1.1 mrg | As in the addition (not in the subtraction!) we could have set 1141 1.1 mrg | one more bit we check this: 1142 1.1 mrg btst IMM (DBL_MANT_DIG+1),d0 1143 1.1 mrg beq 1f 1144 1.1 mrg #ifndef __mcoldfire__ 1145 1.1 mrg lsrl IMM (1),d0 1146 1.1 mrg roxrl IMM (1),d1 1147 1.1 mrg roxrl IMM (1),d2 1148 1.1 mrg roxrl IMM (1),d3 1149 1.1 mrg addw IMM (1),d4 1150 1.1 mrg #else 1151 1.1 mrg lsrl IMM (1),d3 1152 1.1 mrg btst IMM (0),d2 1153 1.1 mrg beq 10f 1154 1.1 mrg bset IMM (31),d3 1155 1.1 mrg 10: lsrl IMM (1),d2 1156 1.1 mrg btst IMM (0),d1 1157 1.1 mrg beq 11f 1158 1.1 mrg bset IMM (31),d2 1159 1.1 mrg 11: lsrl IMM (1),d1 1160 1.1 mrg btst IMM (0),d0 1161 1.1 mrg beq 12f 1162 1.1 mrg bset IMM (31),d1 1163 1.1 mrg 12: lsrl IMM (1),d0 1164 1.1 mrg addl IMM (1),d4 1165 1.1 mrg #endif 1166 1.1 mrg 1: 1167 1.1 mrg lea pc@(Ladddf$5),a0 | to return from rounding routine 1168 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 1169 1.1 mrg #ifdef __mcoldfire__ 1170 1.1 mrg clrl d6 1171 1.1 mrg #endif 1172 1.1 mrg movew a1@(6),d6 | rounding mode in d6 1173 1.1 mrg beq Lround$to$nearest 1174 1.1 mrg #ifndef __mcoldfire__ 1175 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 1176 1.1 mrg #else 1177 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 1178 1.1 mrg #endif 1179 1.1 mrg bhi Lround$to$minus 1180 1.1 mrg blt Lround$to$zero 1181 1.1 mrg bra Lround$to$plus 1182 1.1 mrg Ladddf$5: 1183 1.1 mrg | Put back the exponent and check for overflow 1184 1.1 mrg #ifndef __mcoldfire__ 1185 1.1 mrg cmpw IMM (0x7ff),d4 | is the exponent big? 1186 1.1 mrg #else 1187 1.1 mrg cmpl IMM (0x7ff),d4 | is the exponent big? 1188 1.1 mrg #endif 1189 1.1 mrg bge 1f 1190 1.1 mrg bclr IMM (DBL_MANT_DIG-1),d0 1191 1.1 mrg #ifndef __mcoldfire__ 1192 1.1 mrg lslw IMM (4),d4 | put exponent back into position 1193 1.1 mrg #else 1194 1.1 mrg lsll IMM (4),d4 | put exponent back into position 1195 1.1 mrg #endif 1196 1.1 mrg swap d0 | 1197 1.1 mrg #ifndef __mcoldfire__ 1198 1.1 mrg orw d4,d0 | 1199 1.1 mrg #else 1200 1.1 mrg orl d4,d0 | 1201 1.1 mrg #endif 1202 1.1 mrg swap d0 | 1203 1.1 mrg bra Ladddf$ret 1204 1.1 mrg 1: 1205 1.1 mrg moveq IMM (ADD),d5 1206 1.1 mrg bra Ld$overflow 1207 1.1 mrg 1208 1.1 mrg Lsubdf$0: 1209 1.1 mrg | Here we do the subtraction. 1210 1.1 mrg #ifndef __mcoldfire__ 1211 1.1 mrg exg d7,a0 | put sign back in a0 1212 1.1 mrg exg d6,a3 | 1213 1.1 mrg #else 1214 1.1 mrg movel d7,a4 1215 1.1 mrg movel a0,d7 1216 1.1 mrg movel a4,a0 1217 1.1 mrg movel d6,a4 1218 1.1 mrg movel a3,d6 1219 1.1 mrg movel a4,a3 1220 1.1 mrg #endif 1221 1.1 mrg subl d7,d3 | 1222 1.1 mrg subxl d6,d2 | 1223 1.1 mrg subxl d5,d1 | 1224 1.1 mrg subxl d4,d0 | 1225 1.1 mrg beq Ladddf$ret$1 | if zero just exit 1226 1.1 mrg bpl 1f | if positive skip the following 1227 1.1 mrg movel a0,d7 | 1228 1.1 mrg bchg IMM (31),d7 | change sign bit in d7 1229 1.1 mrg movel d7,a0 | 1230 1.1 mrg negl d3 | 1231 1.1 mrg negxl d2 | 1232 1.1 mrg negxl d1 | and negate result 1233 1.1 mrg negxl d0 | 1234 1.1 mrg 1: 1235 1.1 mrg movel a2,d4 | return exponent to d4 1236 1.1 mrg movel a0,d7 1237 1.1 mrg andl IMM (0x80000000),d7 | isolate sign bit 1238 1.1 mrg #ifndef __mcoldfire__ 1239 1.1 mrg moveml sp@+,a2-a3 | 1240 1.1 mrg #else 1241 1.1 mrg movel sp@+,a4 1242 1.1 mrg movel sp@+,a3 1243 1.1 mrg movel sp@+,a2 1244 1.1 mrg #endif 1245 1.1 mrg 1246 1.1 mrg | Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider 1247 1.1 mrg | the case of denormalized numbers in the rounding routine itself). 1248 1.1 mrg | As in the addition (not in the subtraction!) we could have set 1249 1.1 mrg | one more bit we check this: 1250 1.1 mrg btst IMM (DBL_MANT_DIG+1),d0 1251 1.1 mrg beq 1f 1252 1.1 mrg #ifndef __mcoldfire__ 1253 1.1 mrg lsrl IMM (1),d0 1254 1.1 mrg roxrl IMM (1),d1 1255 1.1 mrg roxrl IMM (1),d2 1256 1.1 mrg roxrl IMM (1),d3 1257 1.1 mrg addw IMM (1),d4 1258 1.1 mrg #else 1259 1.1 mrg lsrl IMM (1),d3 1260 1.1 mrg btst IMM (0),d2 1261 1.1 mrg beq 10f 1262 1.1 mrg bset IMM (31),d3 1263 1.1 mrg 10: lsrl IMM (1),d2 1264 1.1 mrg btst IMM (0),d1 1265 1.1 mrg beq 11f 1266 1.1 mrg bset IMM (31),d2 1267 1.1 mrg 11: lsrl IMM (1),d1 1268 1.1 mrg btst IMM (0),d0 1269 1.1 mrg beq 12f 1270 1.1 mrg bset IMM (31),d1 1271 1.1 mrg 12: lsrl IMM (1),d0 1272 1.1 mrg addl IMM (1),d4 1273 1.1 mrg #endif 1274 1.1 mrg 1: 1275 1.1 mrg lea pc@(Lsubdf$1),a0 | to return from rounding routine 1276 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 1277 1.1 mrg #ifdef __mcoldfire__ 1278 1.1 mrg clrl d6 1279 1.1 mrg #endif 1280 1.1 mrg movew a1@(6),d6 | rounding mode in d6 1281 1.1 mrg beq Lround$to$nearest 1282 1.1 mrg #ifndef __mcoldfire__ 1283 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 1284 1.1 mrg #else 1285 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 1286 1.1 mrg #endif 1287 1.1 mrg bhi Lround$to$minus 1288 1.1 mrg blt Lround$to$zero 1289 1.1 mrg bra Lround$to$plus 1290 1.1 mrg Lsubdf$1: 1291 1.1 mrg | Put back the exponent and sign (we don't have overflow). ' 1292 1.1 mrg bclr IMM (DBL_MANT_DIG-1),d0 1293 1.1 mrg #ifndef __mcoldfire__ 1294 1.1 mrg lslw IMM (4),d4 | put exponent back into position 1295 1.1 mrg #else 1296 1.1 mrg lsll IMM (4),d4 | put exponent back into position 1297 1.1 mrg #endif 1298 1.1 mrg swap d0 | 1299 1.1 mrg #ifndef __mcoldfire__ 1300 1.1 mrg orw d4,d0 | 1301 1.1 mrg #else 1302 1.1 mrg orl d4,d0 | 1303 1.1 mrg #endif 1304 1.1 mrg swap d0 | 1305 1.1 mrg bra Ladddf$ret 1306 1.1 mrg 1307 1.1 mrg | If one of the numbers was too small (difference of exponents >= 1308 1.1 mrg | DBL_MANT_DIG+1) we return the other (and now we don't have to ' 1309 1.1 mrg | check for finiteness or zero). 1310 1.1 mrg Ladddf$a$small: 1311 1.1 mrg #ifndef __mcoldfire__ 1312 1.1 mrg moveml sp@+,a2-a3 1313 1.1 mrg #else 1314 1.1 mrg movel sp@+,a4 1315 1.1 mrg movel sp@+,a3 1316 1.1 mrg movel sp@+,a2 1317 1.1 mrg #endif 1318 1.1 mrg movel a6@(16),d0 1319 1.1 mrg movel a6@(20),d1 1320 1.1 mrg PICLEA SYM (_fpCCR),a0 1321 1.1 mrg movew IMM (0),a0@ 1322 1.1 mrg #ifndef __mcoldfire__ 1323 1.1 mrg moveml sp@+,d2-d7 | restore data registers 1324 1.1 mrg #else 1325 1.1 mrg moveml sp@,d2-d7 1326 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 1327 1.1 mrg | be adjusted here. 1328 1.1 mrg #endif 1329 1.1 mrg unlk a6 | and return 1330 1.1 mrg rts 1331 1.1 mrg 1332 1.1 mrg Ladddf$b$small: 1333 1.1 mrg #ifndef __mcoldfire__ 1334 1.1 mrg moveml sp@+,a2-a3 1335 1.1 mrg #else 1336 1.1 mrg movel sp@+,a4 1337 1.1 mrg movel sp@+,a3 1338 1.1 mrg movel sp@+,a2 1339 1.1 mrg #endif 1340 1.1 mrg movel a6@(8),d0 1341 1.1 mrg movel a6@(12),d1 1342 1.1 mrg PICLEA SYM (_fpCCR),a0 1343 1.1 mrg movew IMM (0),a0@ 1344 1.1 mrg #ifndef __mcoldfire__ 1345 1.1 mrg moveml sp@+,d2-d7 | restore data registers 1346 1.1 mrg #else 1347 1.1 mrg moveml sp@,d2-d7 1348 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 1349 1.1 mrg | be adjusted here. 1350 1.1 mrg #endif 1351 1.1 mrg unlk a6 | and return 1352 1.1 mrg rts 1353 1.1 mrg 1354 1.1 mrg Ladddf$a$den: 1355 1.1 mrg movel d7,d4 | d7 contains 0x00200000 1356 1.1 mrg bra Ladddf$1 1357 1.1 mrg 1358 1.1 mrg Ladddf$b$den: 1359 1.1 mrg movel d7,d5 | d7 contains 0x00200000 1360 1.1 mrg notl d6 1361 1.1 mrg bra Ladddf$2 1362 1.1 mrg 1363 1.1 mrg Ladddf$b: 1364 1.1 mrg | Return b (if a is zero) 1365 1.1 mrg movel d2,d0 1366 1.1 mrg movel d3,d1 1367 1.1 mrg bne 1f | Check if b is -0 1368 1.1 mrg cmpl IMM (0x80000000),d0 1369 1.1 mrg bne 1f 1370 1.1 mrg andl IMM (0x80000000),d7 | Use the sign of a 1371 1.1 mrg clrl d0 1372 1.1 mrg bra Ladddf$ret 1373 1.1 mrg Ladddf$a: 1374 1.1 mrg movel a6@(8),d0 1375 1.1 mrg movel a6@(12),d1 1376 1.1 mrg 1: 1377 1.1 mrg moveq IMM (ADD),d5 1378 1.1 mrg | Check for NaN and +/-INFINITY. 1379 1.1 mrg movel d0,d7 | 1380 1.1 mrg andl IMM (0x80000000),d7 | 1381 1.1 mrg bclr IMM (31),d0 | 1382 1.1 mrg cmpl IMM (0x7ff00000),d0 | 1383 1.1 mrg bge 2f | 1384 1.1 mrg movel d0,d0 | check for zero, since we don't ' 1385 1.1 mrg bne Ladddf$ret | want to return -0 by mistake 1386 1.1 mrg bclr IMM (31),d7 | 1387 1.1 mrg bra Ladddf$ret | 1388 1.1 mrg 2: 1389 1.1 mrg andl IMM (0x000fffff),d0 | check for NaN (nonzero fraction) 1390 1.1 mrg orl d1,d0 | 1391 1.1 mrg bne Ld$inop | 1392 1.1 mrg bra Ld$infty | 1393 1.1 mrg 1394 1.1 mrg Ladddf$ret$1: 1395 1.1 mrg #ifndef __mcoldfire__ 1396 1.1 mrg moveml sp@+,a2-a3 | restore regs and exit 1397 1.1 mrg #else 1398 1.1 mrg movel sp@+,a4 1399 1.1 mrg movel sp@+,a3 1400 1.1 mrg movel sp@+,a2 1401 1.1 mrg #endif 1402 1.1 mrg 1403 1.1 mrg Ladddf$ret: 1404 1.1 mrg | Normal exit. 1405 1.1 mrg PICLEA SYM (_fpCCR),a0 1406 1.1 mrg movew IMM (0),a0@ 1407 1.1 mrg orl d7,d0 | put sign bit back 1408 1.1 mrg #ifndef __mcoldfire__ 1409 1.1 mrg moveml sp@+,d2-d7 1410 1.1 mrg #else 1411 1.1 mrg moveml sp@,d2-d7 1412 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 1413 1.1 mrg | be adjusted here. 1414 1.1 mrg #endif 1415 1.1 mrg unlk a6 1416 1.1 mrg rts 1417 1.1 mrg 1418 1.1 mrg Ladddf$ret$den: 1419 1.1 mrg | Return a denormalized number. 1420 1.1 mrg #ifndef __mcoldfire__ 1421 1.1 mrg lsrl IMM (1),d0 | shift right once more 1422 1.1 mrg roxrl IMM (1),d1 | 1423 1.1 mrg #else 1424 1.1 mrg lsrl IMM (1),d1 1425 1.1 mrg btst IMM (0),d0 1426 1.1 mrg beq 10f 1427 1.1 mrg bset IMM (31),d1 1428 1.1 mrg 10: lsrl IMM (1),d0 1429 1.1 mrg #endif 1430 1.1 mrg bra Ladddf$ret 1431 1.1 mrg 1432 1.1 mrg Ladddf$nf: 1433 1.1 mrg moveq IMM (ADD),d5 1434 1.1 mrg | This could be faster but it is not worth the effort, since it is not 1435 1.1 mrg | executed very often. We sacrifice speed for clarity here. 1436 1.1 mrg movel a6@(8),d0 | get the numbers back (remember that we 1437 1.1 mrg movel a6@(12),d1 | did some processing already) 1438 1.1 mrg movel a6@(16),d2 | 1439 1.1 mrg movel a6@(20),d3 | 1440 1.1 mrg movel IMM (0x7ff00000),d4 | useful constant (INFINITY) 1441 1.1 mrg movel d0,d7 | save sign bits 1442 1.1 mrg movel d2,d6 | 1443 1.1 mrg bclr IMM (31),d0 | clear sign bits 1444 1.1 mrg bclr IMM (31),d2 | 1445 1.1 mrg | We know that one of them is either NaN of +/-INFINITY 1446 1.1 mrg | Check for NaN (if either one is NaN return NaN) 1447 1.1 mrg cmpl d4,d0 | check first a (d0) 1448 1.1 mrg bhi Ld$inop | if d0 > 0x7ff00000 or equal and 1449 1.1 mrg bne 2f 1450 1.1 mrg tstl d1 | d1 > 0, a is NaN 1451 1.1 mrg bne Ld$inop | 1452 1.1 mrg 2: cmpl d4,d2 | check now b (d1) 1453 1.1 mrg bhi Ld$inop | 1454 1.1 mrg bne 3f 1455 1.1 mrg tstl d3 | 1456 1.1 mrg bne Ld$inop | 1457 1.1 mrg 3: 1458 1.1 mrg | Now comes the check for +/-INFINITY. We know that both are (maybe not 1459 1.1 mrg | finite) numbers, but we have to check if both are infinite whether we 1460 1.1 mrg | are adding or subtracting them. 1461 1.1 mrg eorl d7,d6 | to check sign bits 1462 1.1 mrg bmi 1f 1463 1.1 mrg andl IMM (0x80000000),d7 | get (common) sign bit 1464 1.1 mrg bra Ld$infty 1465 1.1 mrg 1: 1466 1.1 mrg | We know one (or both) are infinite, so we test for equality between the 1467 1.1 mrg | two numbers (if they are equal they have to be infinite both, so we 1468 1.1 mrg | return NaN). 1469 1.1 mrg cmpl d2,d0 | are both infinite? 1470 1.1 mrg bne 1f | if d0 <> d2 they are not equal 1471 1.1 mrg cmpl d3,d1 | if d0 == d2 test d3 and d1 1472 1.1 mrg beq Ld$inop | if equal return NaN 1473 1.1 mrg 1: 1474 1.1 mrg andl IMM (0x80000000),d7 | get a's sign bit ' 1475 1.1 mrg cmpl d4,d0 | test now for infinity 1476 1.1 mrg beq Ld$infty | if a is INFINITY return with this sign 1477 1.1 mrg bchg IMM (31),d7 | else we know b is INFINITY and has 1478 1.1 mrg bra Ld$infty | the opposite sign 1479 1.1 mrg 1480 1.1 mrg |============================================================================= 1481 1.1 mrg | __muldf3 1482 1.1 mrg |============================================================================= 1483 1.1 mrg 1484 1.1 mrg | double __muldf3(double, double); 1485 1.1 mrg FUNC(__muldf3) 1486 1.1 mrg SYM (__muldf3): 1487 1.1 mrg #ifndef __mcoldfire__ 1488 1.1 mrg link a6,IMM (0) 1489 1.1 mrg moveml d2-d7,sp@- 1490 1.1 mrg #else 1491 1.1 mrg link a6,IMM (-24) 1492 1.1 mrg moveml d2-d7,sp@ 1493 1.1 mrg #endif 1494 1.1 mrg movel a6@(8),d0 | get a into d0-d1 1495 1.1 mrg movel a6@(12),d1 | 1496 1.1 mrg movel a6@(16),d2 | and b into d2-d3 1497 1.1 mrg movel a6@(20),d3 | 1498 1.1 mrg movel d0,d7 | d7 will hold the sign of the product 1499 1.1 mrg eorl d2,d7 | 1500 1.1 mrg andl IMM (0x80000000),d7 | 1501 1.1 mrg movel d7,a0 | save sign bit into a0 1502 1.1 mrg movel IMM (0x7ff00000),d7 | useful constant (+INFINITY) 1503 1.1 mrg movel d7,d6 | another (mask for fraction) 1504 1.1 mrg notl d6 | 1505 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 1506 1.1 mrg movel d0,d4 | 1507 1.1 mrg orl d1,d4 | 1508 1.1 mrg beq Lmuldf$a$0 | branch if a is zero 1509 1.1 mrg movel d0,d4 | 1510 1.1 mrg bclr IMM (31),d2 | get rid of b's sign bit ' 1511 1.1 mrg movel d2,d5 | 1512 1.1 mrg orl d3,d5 | 1513 1.1 mrg beq Lmuldf$b$0 | branch if b is zero 1514 1.1 mrg movel d2,d5 | 1515 1.1 mrg cmpl d7,d0 | is a big? 1516 1.1 mrg bhi Lmuldf$inop | if a is NaN return NaN 1517 1.1 mrg beq Lmuldf$a$nf | we still have to check d1 and b ... 1518 1.1 mrg cmpl d7,d2 | now compare b with INFINITY 1519 1.1 mrg bhi Lmuldf$inop | is b NaN? 1520 1.1 mrg beq Lmuldf$b$nf | we still have to check d3 ... 1521 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 1522 1.1 mrg | Now we get the exponents into d4 and d5. 1523 1.1 mrg andl d7,d4 | isolate exponent in d4 1524 1.1 mrg beq Lmuldf$a$den | if exponent zero, have denormalized 1525 1.1 mrg andl d6,d0 | isolate fraction 1526 1.1 mrg orl IMM (0x00100000),d0 | and put hidden bit back 1527 1.1 mrg swap d4 | I like exponents in the first byte 1528 1.1 mrg #ifndef __mcoldfire__ 1529 1.1 mrg lsrw IMM (4),d4 | 1530 1.1 mrg #else 1531 1.1 mrg lsrl IMM (4),d4 | 1532 1.1 mrg #endif 1533 1.1 mrg Lmuldf$1: 1534 1.1 mrg andl d7,d5 | 1535 1.1 mrg beq Lmuldf$b$den | 1536 1.1 mrg andl d6,d2 | 1537 1.1 mrg orl IMM (0x00100000),d2 | and put hidden bit back 1538 1.1 mrg swap d5 | 1539 1.1 mrg #ifndef __mcoldfire__ 1540 1.1 mrg lsrw IMM (4),d5 | 1541 1.1 mrg #else 1542 1.1 mrg lsrl IMM (4),d5 | 1543 1.1 mrg #endif 1544 1.1 mrg Lmuldf$2: | 1545 1.1 mrg #ifndef __mcoldfire__ 1546 1.1 mrg addw d5,d4 | add exponents 1547 1.1 mrg subw IMM (D_BIAS+1),d4 | and subtract bias (plus one) 1548 1.1 mrg #else 1549 1.1 mrg addl d5,d4 | add exponents 1550 1.1 mrg subl IMM (D_BIAS+1),d4 | and subtract bias (plus one) 1551 1.1 mrg #endif 1552 1.1 mrg 1553 1.1 mrg | We are now ready to do the multiplication. The situation is as follows: 1554 1.1 mrg | both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were 1555 1.1 mrg | denormalized to start with!), which means that in the product bit 104 1556 1.1 mrg | (which will correspond to bit 8 of the fourth long) is set. 1557 1.1 mrg 1558 1.1 mrg | Here we have to do the product. 1559 1.1 mrg | To do it we have to juggle the registers back and forth, as there are not 1560 1.1 mrg | enough to keep everything in them. So we use the address registers to keep 1561 1.1 mrg | some intermediate data. 1562 1.1 mrg 1563 1.1 mrg #ifndef __mcoldfire__ 1564 1.1 mrg moveml a2-a3,sp@- | save a2 and a3 for temporary use 1565 1.1 mrg #else 1566 1.1 mrg movel a2,sp@- 1567 1.1 mrg movel a3,sp@- 1568 1.1 mrg movel a4,sp@- 1569 1.1 mrg #endif 1570 1.1 mrg movel IMM (0),a2 | a2 is a null register 1571 1.1 mrg movel d4,a3 | and a3 will preserve the exponent 1572 1.1 mrg 1573 1.1 mrg | First, shift d2-d3 so bit 20 becomes bit 31: 1574 1.1 mrg #ifndef __mcoldfire__ 1575 1.1 mrg rorl IMM (5),d2 | rotate d2 5 places right 1576 1.1 mrg swap d2 | and swap it 1577 1.1 mrg rorl IMM (5),d3 | do the same thing with d3 1578 1.1 mrg swap d3 | 1579 1.1 mrg movew d3,d6 | get the rightmost 11 bits of d3 1580 1.1 mrg andw IMM (0x07ff),d6 | 1581 1.1 mrg orw d6,d2 | and put them into d2 1582 1.1 mrg andw IMM (0xf800),d3 | clear those bits in d3 1583 1.1 mrg #else 1584 1.1 mrg moveq IMM (11),d7 | left shift d2 11 bits 1585 1.1 mrg lsll d7,d2 1586 1.1 mrg movel d3,d6 | get a copy of d3 1587 1.1 mrg lsll d7,d3 | left shift d3 11 bits 1588 1.1 mrg andl IMM (0xffe00000),d6 | get the top 11 bits of d3 1589 1.1 mrg moveq IMM (21),d7 | right shift them 21 bits 1590 1.1 mrg lsrl d7,d6 1591 1.1 mrg orl d6,d2 | stick them at the end of d2 1592 1.1 mrg #endif 1593 1.1 mrg 1594 1.1 mrg movel d2,d6 | move b into d6-d7 1595 1.1 mrg movel d3,d7 | move a into d4-d5 1596 1.1 mrg movel d0,d4 | and clear d0-d1-d2-d3 (to put result) 1597 1.1 mrg movel d1,d5 | 1598 1.1 mrg movel IMM (0),d3 | 1599 1.1 mrg movel d3,d2 | 1600 1.1 mrg movel d3,d1 | 1601 1.1 mrg movel d3,d0 | 1602 1.1 mrg 1603 1.1 mrg | We use a1 as counter: 1604 1.1 mrg movel IMM (DBL_MANT_DIG-1),a1 1605 1.1 mrg #ifndef __mcoldfire__ 1606 1.1 mrg exg d7,a1 1607 1.1 mrg #else 1608 1.1 mrg movel d7,a4 1609 1.1 mrg movel a1,d7 1610 1.1 mrg movel a4,a1 1611 1.1 mrg #endif 1612 1.1 mrg 1613 1.1 mrg 1: 1614 1.1 mrg #ifndef __mcoldfire__ 1615 1.1 mrg exg d7,a1 | put counter back in a1 1616 1.1 mrg #else 1617 1.1 mrg movel d7,a4 1618 1.1 mrg movel a1,d7 1619 1.1 mrg movel a4,a1 1620 1.1 mrg #endif 1621 1.1 mrg addl d3,d3 | shift sum once left 1622 1.1 mrg addxl d2,d2 | 1623 1.1 mrg addxl d1,d1 | 1624 1.1 mrg addxl d0,d0 | 1625 1.1 mrg addl d7,d7 | 1626 1.1 mrg addxl d6,d6 | 1627 1.1 mrg bcc 2f | if bit clear skip the following 1628 1.1 mrg #ifndef __mcoldfire__ 1629 1.1 mrg exg d7,a2 | 1630 1.1 mrg #else 1631 1.1 mrg movel d7,a4 1632 1.1 mrg movel a2,d7 1633 1.1 mrg movel a4,a2 1634 1.1 mrg #endif 1635 1.1 mrg addl d5,d3 | else add a to the sum 1636 1.1 mrg addxl d4,d2 | 1637 1.1 mrg addxl d7,d1 | 1638 1.1 mrg addxl d7,d0 | 1639 1.1 mrg #ifndef __mcoldfire__ 1640 1.1 mrg exg d7,a2 | 1641 1.1 mrg #else 1642 1.1 mrg movel d7,a4 1643 1.1 mrg movel a2,d7 1644 1.1 mrg movel a4,a2 1645 1.1 mrg #endif 1646 1.1 mrg 2: 1647 1.1 mrg #ifndef __mcoldfire__ 1648 1.1 mrg exg d7,a1 | put counter in d7 1649 1.1 mrg dbf d7,1b | decrement and branch 1650 1.1 mrg #else 1651 1.1 mrg movel d7,a4 1652 1.1 mrg movel a1,d7 1653 1.1 mrg movel a4,a1 1654 1.1 mrg subql IMM (1),d7 1655 1.1 mrg bpl 1b 1656 1.1 mrg #endif 1657 1.1 mrg 1658 1.1 mrg movel a3,d4 | restore exponent 1659 1.1 mrg #ifndef __mcoldfire__ 1660 1.1 mrg moveml sp@+,a2-a3 1661 1.1 mrg #else 1662 1.1 mrg movel sp@+,a4 1663 1.1 mrg movel sp@+,a3 1664 1.1 mrg movel sp@+,a2 1665 1.1 mrg #endif 1666 1.1 mrg 1667 1.1 mrg | Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The 1668 1.1 mrg | first thing to do now is to normalize it so bit 8 becomes bit 1669 1.1 mrg | DBL_MANT_DIG-32 (to do the rounding); later we will shift right. 1670 1.1 mrg swap d0 1671 1.1 mrg swap d1 1672 1.1 mrg movew d1,d0 1673 1.1 mrg swap d2 1674 1.1 mrg movew d2,d1 1675 1.1 mrg swap d3 1676 1.1 mrg movew d3,d2 1677 1.1 mrg movew IMM (0),d3 1678 1.1 mrg #ifndef __mcoldfire__ 1679 1.1 mrg lsrl IMM (1),d0 1680 1.1 mrg roxrl IMM (1),d1 1681 1.1 mrg roxrl IMM (1),d2 1682 1.1 mrg roxrl IMM (1),d3 1683 1.1 mrg lsrl IMM (1),d0 1684 1.1 mrg roxrl IMM (1),d1 1685 1.1 mrg roxrl IMM (1),d2 1686 1.1 mrg roxrl IMM (1),d3 1687 1.1 mrg lsrl IMM (1),d0 1688 1.1 mrg roxrl IMM (1),d1 1689 1.1 mrg roxrl IMM (1),d2 1690 1.1 mrg roxrl IMM (1),d3 1691 1.1 mrg #else 1692 1.1 mrg moveq IMM (29),d6 1693 1.1 mrg lsrl IMM (3),d3 1694 1.1 mrg movel d2,d7 1695 1.1 mrg lsll d6,d7 1696 1.1 mrg orl d7,d3 1697 1.1 mrg lsrl IMM (3),d2 1698 1.1 mrg movel d1,d7 1699 1.1 mrg lsll d6,d7 1700 1.1 mrg orl d7,d2 1701 1.1 mrg lsrl IMM (3),d1 1702 1.1 mrg movel d0,d7 1703 1.1 mrg lsll d6,d7 1704 1.1 mrg orl d7,d1 1705 1.1 mrg lsrl IMM (3),d0 1706 1.1 mrg #endif 1707 1.1 mrg 1708 1.1 mrg | Now round, check for over- and underflow, and exit. 1709 1.1 mrg movel a0,d7 | get sign bit back into d7 1710 1.1 mrg moveq IMM (MULTIPLY),d5 1711 1.1 mrg 1712 1.1 mrg btst IMM (DBL_MANT_DIG+1-32),d0 1713 1.1 mrg beq Lround$exit 1714 1.1 mrg #ifndef __mcoldfire__ 1715 1.1 mrg lsrl IMM (1),d0 1716 1.1 mrg roxrl IMM (1),d1 1717 1.1 mrg addw IMM (1),d4 1718 1.1 mrg #else 1719 1.1 mrg lsrl IMM (1),d1 1720 1.1 mrg btst IMM (0),d0 1721 1.1 mrg beq 10f 1722 1.1 mrg bset IMM (31),d1 1723 1.1 mrg 10: lsrl IMM (1),d0 1724 1.1 mrg addl IMM (1),d4 1725 1.1 mrg #endif 1726 1.1 mrg bra Lround$exit 1727 1.1 mrg 1728 1.1 mrg Lmuldf$inop: 1729 1.1 mrg moveq IMM (MULTIPLY),d5 1730 1.1 mrg bra Ld$inop 1731 1.1 mrg 1732 1.1 mrg Lmuldf$b$nf: 1733 1.1 mrg moveq IMM (MULTIPLY),d5 1734 1.1 mrg movel a0,d7 | get sign bit back into d7 1735 1.1 mrg tstl d3 | we know d2 == 0x7ff00000, so check d3 1736 1.1 mrg bne Ld$inop | if d3 <> 0 b is NaN 1737 1.1 mrg bra Ld$overflow | else we have overflow (since a is finite) 1738 1.1 mrg 1739 1.1 mrg Lmuldf$a$nf: 1740 1.1 mrg moveq IMM (MULTIPLY),d5 1741 1.1 mrg movel a0,d7 | get sign bit back into d7 1742 1.1 mrg tstl d1 | we know d0 == 0x7ff00000, so check d1 1743 1.1 mrg bne Ld$inop | if d1 <> 0 a is NaN 1744 1.1 mrg bra Ld$overflow | else signal overflow 1745 1.1 mrg 1746 1.1 mrg | If either number is zero return zero, unless the other is +/-INFINITY or 1747 1.1 mrg | NaN, in which case we return NaN. 1748 1.1 mrg Lmuldf$b$0: 1749 1.1 mrg moveq IMM (MULTIPLY),d5 1750 1.1 mrg #ifndef __mcoldfire__ 1751 1.1 mrg exg d2,d0 | put b (==0) into d0-d1 1752 1.1 mrg exg d3,d1 | and a (with sign bit cleared) into d2-d3 1753 1.1 mrg movel a0,d0 | set result sign 1754 1.1 mrg #else 1755 1.1 mrg movel d0,d2 | put a into d2-d3 1756 1.1 mrg movel d1,d3 1757 1.1 mrg movel a0,d0 | put result zero into d0-d1 1758 1.1 mrg movq IMM(0),d1 1759 1.1 mrg #endif 1760 1.1 mrg bra 1f 1761 1.1 mrg Lmuldf$a$0: 1762 1.1 mrg movel a0,d0 | set result sign 1763 1.1 mrg movel a6@(16),d2 | put b into d2-d3 again 1764 1.1 mrg movel a6@(20),d3 | 1765 1.1 mrg bclr IMM (31),d2 | clear sign bit 1766 1.1 mrg 1: cmpl IMM (0x7ff00000),d2 | check for non-finiteness 1767 1.1 mrg bge Ld$inop | in case NaN or +/-INFINITY return NaN 1768 1.1 mrg PICLEA SYM (_fpCCR),a0 1769 1.1 mrg movew IMM (0),a0@ 1770 1.1 mrg #ifndef __mcoldfire__ 1771 1.1 mrg moveml sp@+,d2-d7 1772 1.1 mrg #else 1773 1.1 mrg moveml sp@,d2-d7 1774 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 1775 1.1 mrg | be adjusted here. 1776 1.1 mrg #endif 1777 1.1 mrg unlk a6 1778 1.1 mrg rts 1779 1.1 mrg 1780 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 1781 1.1 mrg | hidden bit back into the fraction; instead we shift left until bit 21 1782 1.1 mrg | (the hidden bit) is set, adjusting the exponent accordingly. We do this 1783 1.1 mrg | to ensure that the product of the fractions is close to 1. 1784 1.1 mrg Lmuldf$a$den: 1785 1.1 mrg movel IMM (1),d4 1786 1.1 mrg andl d6,d0 1787 1.1 mrg 1: addl d1,d1 | shift a left until bit 20 is set 1788 1.1 mrg addxl d0,d0 | 1789 1.1 mrg #ifndef __mcoldfire__ 1790 1.1 mrg subw IMM (1),d4 | and adjust exponent 1791 1.1 mrg #else 1792 1.1 mrg subl IMM (1),d4 | and adjust exponent 1793 1.1 mrg #endif 1794 1.1 mrg btst IMM (20),d0 | 1795 1.1 mrg bne Lmuldf$1 | 1796 1.1 mrg bra 1b 1797 1.1 mrg 1798 1.1 mrg Lmuldf$b$den: 1799 1.1 mrg movel IMM (1),d5 1800 1.1 mrg andl d6,d2 1801 1.1 mrg 1: addl d3,d3 | shift b left until bit 20 is set 1802 1.1 mrg addxl d2,d2 | 1803 1.1 mrg #ifndef __mcoldfire__ 1804 1.1 mrg subw IMM (1),d5 | and adjust exponent 1805 1.1 mrg #else 1806 1.1 mrg subql IMM (1),d5 | and adjust exponent 1807 1.1 mrg #endif 1808 1.1 mrg btst IMM (20),d2 | 1809 1.1 mrg bne Lmuldf$2 | 1810 1.1 mrg bra 1b 1811 1.1 mrg 1812 1.1 mrg 1813 1.1 mrg |============================================================================= 1814 1.1 mrg | __divdf3 1815 1.1 mrg |============================================================================= 1816 1.1 mrg 1817 1.1 mrg | double __divdf3(double, double); 1818 1.1 mrg FUNC(__divdf3) 1819 1.1 mrg SYM (__divdf3): 1820 1.1 mrg #ifndef __mcoldfire__ 1821 1.1 mrg link a6,IMM (0) 1822 1.1 mrg moveml d2-d7,sp@- 1823 1.1 mrg #else 1824 1.1 mrg link a6,IMM (-24) 1825 1.1 mrg moveml d2-d7,sp@ 1826 1.1 mrg #endif 1827 1.1 mrg movel a6@(8),d0 | get a into d0-d1 1828 1.1 mrg movel a6@(12),d1 | 1829 1.1 mrg movel a6@(16),d2 | and b into d2-d3 1830 1.1 mrg movel a6@(20),d3 | 1831 1.1 mrg movel d0,d7 | d7 will hold the sign of the result 1832 1.1 mrg eorl d2,d7 | 1833 1.1 mrg andl IMM (0x80000000),d7 1834 1.1 mrg movel d7,a0 | save sign into a0 1835 1.1 mrg movel IMM (0x7ff00000),d7 | useful constant (+INFINITY) 1836 1.1 mrg movel d7,d6 | another (mask for fraction) 1837 1.1 mrg notl d6 | 1838 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 1839 1.1 mrg movel d0,d4 | 1840 1.1 mrg orl d1,d4 | 1841 1.1 mrg beq Ldivdf$a$0 | branch if a is zero 1842 1.1 mrg movel d0,d4 | 1843 1.1 mrg bclr IMM (31),d2 | get rid of b's sign bit ' 1844 1.1 mrg movel d2,d5 | 1845 1.1 mrg orl d3,d5 | 1846 1.1 mrg beq Ldivdf$b$0 | branch if b is zero 1847 1.1 mrg movel d2,d5 1848 1.1 mrg cmpl d7,d0 | is a big? 1849 1.1 mrg bhi Ldivdf$inop | if a is NaN return NaN 1850 1.1 mrg beq Ldivdf$a$nf | if d0 == 0x7ff00000 we check d1 1851 1.1 mrg cmpl d7,d2 | now compare b with INFINITY 1852 1.1 mrg bhi Ldivdf$inop | if b is NaN return NaN 1853 1.1 mrg beq Ldivdf$b$nf | if d2 == 0x7ff00000 we check d3 1854 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 1855 1.1 mrg | Now we get the exponents into d4 and d5 and normalize the numbers to 1856 1.1 mrg | ensure that the ratio of the fractions is around 1. We do this by 1857 1.1 mrg | making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit) 1858 1.1 mrg | set, even if they were denormalized to start with. 1859 1.1 mrg | Thus, the result will satisfy: 2 > result > 1/2. 1860 1.1 mrg andl d7,d4 | and isolate exponent in d4 1861 1.1 mrg beq Ldivdf$a$den | if exponent is zero we have a denormalized 1862 1.1 mrg andl d6,d0 | and isolate fraction 1863 1.1 mrg orl IMM (0x00100000),d0 | and put hidden bit back 1864 1.1 mrg swap d4 | I like exponents in the first byte 1865 1.1 mrg #ifndef __mcoldfire__ 1866 1.1 mrg lsrw IMM (4),d4 | 1867 1.1 mrg #else 1868 1.1 mrg lsrl IMM (4),d4 | 1869 1.1 mrg #endif 1870 1.1 mrg Ldivdf$1: | 1871 1.1 mrg andl d7,d5 | 1872 1.1 mrg beq Ldivdf$b$den | 1873 1.1 mrg andl d6,d2 | 1874 1.1 mrg orl IMM (0x00100000),d2 1875 1.1 mrg swap d5 | 1876 1.1 mrg #ifndef __mcoldfire__ 1877 1.1 mrg lsrw IMM (4),d5 | 1878 1.1 mrg #else 1879 1.1 mrg lsrl IMM (4),d5 | 1880 1.1 mrg #endif 1881 1.1 mrg Ldivdf$2: | 1882 1.1 mrg #ifndef __mcoldfire__ 1883 1.1 mrg subw d5,d4 | subtract exponents 1884 1.1 mrg addw IMM (D_BIAS),d4 | and add bias 1885 1.1 mrg #else 1886 1.1 mrg subl d5,d4 | subtract exponents 1887 1.1 mrg addl IMM (D_BIAS),d4 | and add bias 1888 1.1 mrg #endif 1889 1.1 mrg 1890 1.1 mrg | We are now ready to do the division. We have prepared things in such a way 1891 1.1 mrg | that the ratio of the fractions will be less than 2 but greater than 1/2. 1892 1.1 mrg | At this point the registers in use are: 1893 1.1 mrg | d0-d1 hold a (first operand, bit DBL_MANT_DIG-32=0, bit 1894 1.1 mrg | DBL_MANT_DIG-1-32=1) 1895 1.1 mrg | d2-d3 hold b (second operand, bit DBL_MANT_DIG-32=1) 1896 1.1 mrg | d4 holds the difference of the exponents, corrected by the bias 1897 1.1 mrg | a0 holds the sign of the ratio 1898 1.1 mrg 1899 1.1 mrg | To do the rounding correctly we need to keep information about the 1900 1.1 mrg | nonsignificant bits. One way to do this would be to do the division 1901 1.1 mrg | using four registers; another is to use two registers (as originally 1902 1.1 mrg | I did), but use a sticky bit to preserve information about the 1903 1.1 mrg | fractional part. Note that we can keep that info in a1, which is not 1904 1.1 mrg | used. 1905 1.1 mrg movel IMM (0),d6 | d6-d7 will hold the result 1906 1.1 mrg movel d6,d7 | 1907 1.1 mrg movel IMM (0),a1 | and a1 will hold the sticky bit 1908 1.1 mrg 1909 1.1 mrg movel IMM (DBL_MANT_DIG-32+1),d5 1910 1.1 mrg 1911 1.1 mrg 1: cmpl d0,d2 | is a < b? 1912 1.1 mrg bhi 3f | if b > a skip the following 1913 1.1 mrg beq 4f | if d0==d2 check d1 and d3 1914 1.1 mrg 2: subl d3,d1 | 1915 1.1 mrg subxl d2,d0 | a <-- a - b 1916 1.1 mrg bset d5,d6 | set the corresponding bit in d6 1917 1.1 mrg 3: addl d1,d1 | shift a by 1 1918 1.1 mrg addxl d0,d0 | 1919 1.1 mrg #ifndef __mcoldfire__ 1920 1.1 mrg dbra d5,1b | and branch back 1921 1.1 mrg #else 1922 1.1 mrg subql IMM (1), d5 1923 1.1 mrg bpl 1b 1924 1.1 mrg #endif 1925 1.1 mrg bra 5f 1926 1.1 mrg 4: cmpl d1,d3 | here d0==d2, so check d1 and d3 1927 1.1 mrg bhi 3b | if d1 > d2 skip the subtraction 1928 1.1 mrg bra 2b | else go do it 1929 1.1 mrg 5: 1930 1.1 mrg | Here we have to start setting the bits in the second long. 1931 1.1 mrg movel IMM (31),d5 | again d5 is counter 1932 1.1 mrg 1933 1.1 mrg 1: cmpl d0,d2 | is a < b? 1934 1.1 mrg bhi 3f | if b > a skip the following 1935 1.1 mrg beq 4f | if d0==d2 check d1 and d3 1936 1.1 mrg 2: subl d3,d1 | 1937 1.1 mrg subxl d2,d0 | a <-- a - b 1938 1.1 mrg bset d5,d7 | set the corresponding bit in d7 1939 1.1 mrg 3: addl d1,d1 | shift a by 1 1940 1.1 mrg addxl d0,d0 | 1941 1.1 mrg #ifndef __mcoldfire__ 1942 1.1 mrg dbra d5,1b | and branch back 1943 1.1 mrg #else 1944 1.1 mrg subql IMM (1), d5 1945 1.1 mrg bpl 1b 1946 1.1 mrg #endif 1947 1.1 mrg bra 5f 1948 1.1 mrg 4: cmpl d1,d3 | here d0==d2, so check d1 and d3 1949 1.1 mrg bhi 3b | if d1 > d2 skip the subtraction 1950 1.1 mrg bra 2b | else go do it 1951 1.1 mrg 5: 1952 1.1 mrg | Now go ahead checking until we hit a one, which we store in d2. 1953 1.1 mrg movel IMM (DBL_MANT_DIG),d5 1954 1.1 mrg 1: cmpl d2,d0 | is a < b? 1955 1.1 mrg bhi 4f | if b < a, exit 1956 1.1 mrg beq 3f | if d0==d2 check d1 and d3 1957 1.1 mrg 2: addl d1,d1 | shift a by 1 1958 1.1 mrg addxl d0,d0 | 1959 1.1 mrg #ifndef __mcoldfire__ 1960 1.1 mrg dbra d5,1b | and branch back 1961 1.1 mrg #else 1962 1.1 mrg subql IMM (1), d5 1963 1.1 mrg bpl 1b 1964 1.1 mrg #endif 1965 1.1 mrg movel IMM (0),d2 | here no sticky bit was found 1966 1.1 mrg movel d2,d3 1967 1.1 mrg bra 5f 1968 1.1 mrg 3: cmpl d1,d3 | here d0==d2, so check d1 and d3 1969 1.1 mrg bhi 2b | if d1 > d2 go back 1970 1.1 mrg 4: 1971 1.1 mrg | Here put the sticky bit in d2-d3 (in the position which actually corresponds 1972 1.1 mrg | to it; if you don't do this the algorithm loses in some cases). ' 1973 1.1 mrg movel IMM (0),d2 1974 1.1 mrg movel d2,d3 1975 1.1 mrg #ifndef __mcoldfire__ 1976 1.1 mrg subw IMM (DBL_MANT_DIG),d5 1977 1.1 mrg addw IMM (63),d5 1978 1.1 mrg cmpw IMM (31),d5 1979 1.1 mrg #else 1980 1.1 mrg subl IMM (DBL_MANT_DIG),d5 1981 1.1 mrg addl IMM (63),d5 1982 1.1 mrg cmpl IMM (31),d5 1983 1.1 mrg #endif 1984 1.1 mrg bhi 2f 1985 1.1 mrg 1: bset d5,d3 1986 1.1 mrg bra 5f 1987 1.1 mrg #ifndef __mcoldfire__ 1988 1.1 mrg subw IMM (32),d5 1989 1.1 mrg #else 1990 1.1 mrg subl IMM (32),d5 1991 1.1 mrg #endif 1992 1.1 mrg 2: bset d5,d2 1993 1.1 mrg 5: 1994 1.1 mrg | Finally we are finished! Move the longs in the address registers to 1995 1.1 mrg | their final destination: 1996 1.1 mrg movel d6,d0 1997 1.1 mrg movel d7,d1 1998 1.1 mrg movel IMM (0),d3 1999 1.1 mrg 2000 1.1 mrg | Here we have finished the division, with the result in d0-d1-d2-d3, with 2001 1.1 mrg | 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set. 2002 1.1 mrg | If it is not, then definitely bit 21 is set. Normalize so bit 22 is 2003 1.1 mrg | not set: 2004 1.1 mrg btst IMM (DBL_MANT_DIG-32+1),d0 2005 1.1 mrg beq 1f 2006 1.1 mrg #ifndef __mcoldfire__ 2007 1.1 mrg lsrl IMM (1),d0 2008 1.1 mrg roxrl IMM (1),d1 2009 1.1 mrg roxrl IMM (1),d2 2010 1.1 mrg roxrl IMM (1),d3 2011 1.1 mrg addw IMM (1),d4 2012 1.1 mrg #else 2013 1.1 mrg lsrl IMM (1),d3 2014 1.1 mrg btst IMM (0),d2 2015 1.1 mrg beq 10f 2016 1.1 mrg bset IMM (31),d3 2017 1.1 mrg 10: lsrl IMM (1),d2 2018 1.1 mrg btst IMM (0),d1 2019 1.1 mrg beq 11f 2020 1.1 mrg bset IMM (31),d2 2021 1.1 mrg 11: lsrl IMM (1),d1 2022 1.1 mrg btst IMM (0),d0 2023 1.1 mrg beq 12f 2024 1.1 mrg bset IMM (31),d1 2025 1.1 mrg 12: lsrl IMM (1),d0 2026 1.1 mrg addl IMM (1),d4 2027 1.1 mrg #endif 2028 1.1 mrg 1: 2029 1.1 mrg | Now round, check for over- and underflow, and exit. 2030 1.1 mrg movel a0,d7 | restore sign bit to d7 2031 1.1 mrg moveq IMM (DIVIDE),d5 2032 1.1 mrg bra Lround$exit 2033 1.1 mrg 2034 1.1 mrg Ldivdf$inop: 2035 1.1 mrg moveq IMM (DIVIDE),d5 2036 1.1 mrg bra Ld$inop 2037 1.1 mrg 2038 1.1 mrg Ldivdf$a$0: 2039 1.1 mrg | If a is zero check to see whether b is zero also. In that case return 2040 1.1 mrg | NaN; then check if b is NaN, and return NaN also in that case. Else 2041 1.1 mrg | return a properly signed zero. 2042 1.1 mrg moveq IMM (DIVIDE),d5 2043 1.1 mrg bclr IMM (31),d2 | 2044 1.1 mrg movel d2,d4 | 2045 1.1 mrg orl d3,d4 | 2046 1.1 mrg beq Ld$inop | if b is also zero return NaN 2047 1.1 mrg cmpl IMM (0x7ff00000),d2 | check for NaN 2048 1.1 mrg bhi Ld$inop | 2049 1.1 mrg blt 1f | 2050 1.1 mrg tstl d3 | 2051 1.1 mrg bne Ld$inop | 2052 1.1 mrg 1: movel a0,d0 | else return signed zero 2053 1.1 mrg moveq IMM(0),d1 | 2054 1.1 mrg PICLEA SYM (_fpCCR),a0 | clear exception flags 2055 1.1 mrg movew IMM (0),a0@ | 2056 1.1 mrg #ifndef __mcoldfire__ 2057 1.1 mrg moveml sp@+,d2-d7 | 2058 1.1 mrg #else 2059 1.1 mrg moveml sp@,d2-d7 | 2060 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2061 1.1 mrg | be adjusted here. 2062 1.1 mrg #endif 2063 1.1 mrg unlk a6 | 2064 1.1 mrg rts | 2065 1.1 mrg 2066 1.1 mrg Ldivdf$b$0: 2067 1.1 mrg moveq IMM (DIVIDE),d5 2068 1.1 mrg | If we got here a is not zero. Check if a is NaN; in that case return NaN, 2069 1.1 mrg | else return +/-INFINITY. Remember that a is in d0 with the sign bit 2070 1.1 mrg | cleared already. 2071 1.1 mrg movel a0,d7 | put a's sign bit back in d7 ' 2072 1.1 mrg cmpl IMM (0x7ff00000),d0 | compare d0 with INFINITY 2073 1.1 mrg bhi Ld$inop | if larger it is NaN 2074 1.1 mrg tstl d1 | 2075 1.1 mrg bne Ld$inop | 2076 1.1 mrg bra Ld$div$0 | else signal DIVIDE_BY_ZERO 2077 1.1 mrg 2078 1.1 mrg Ldivdf$b$nf: 2079 1.1 mrg moveq IMM (DIVIDE),d5 2080 1.1 mrg | If d2 == 0x7ff00000 we have to check d3. 2081 1.1 mrg tstl d3 | 2082 1.1 mrg bne Ld$inop | if d3 <> 0, b is NaN 2083 1.1 mrg bra Ld$underflow | else b is +/-INFINITY, so signal underflow 2084 1.1 mrg 2085 1.1 mrg Ldivdf$a$nf: 2086 1.1 mrg moveq IMM (DIVIDE),d5 2087 1.1 mrg | If d0 == 0x7ff00000 we have to check d1. 2088 1.1 mrg tstl d1 | 2089 1.1 mrg bne Ld$inop | if d1 <> 0, a is NaN 2090 1.1 mrg | If a is INFINITY we have to check b 2091 1.1 mrg cmpl d7,d2 | compare b with INFINITY 2092 1.1 mrg bge Ld$inop | if b is NaN or INFINITY return NaN 2093 1.1 mrg tstl d3 | 2094 1.1 mrg bne Ld$inop | 2095 1.1 mrg bra Ld$overflow | else return overflow 2096 1.1 mrg 2097 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 2098 1.1 mrg | bit back into the fraction. 2099 1.1 mrg Ldivdf$a$den: 2100 1.1 mrg movel IMM (1),d4 2101 1.1 mrg andl d6,d0 2102 1.1 mrg 1: addl d1,d1 | shift a left until bit 20 is set 2103 1.1 mrg addxl d0,d0 2104 1.1 mrg #ifndef __mcoldfire__ 2105 1.1 mrg subw IMM (1),d4 | and adjust exponent 2106 1.1 mrg #else 2107 1.1 mrg subl IMM (1),d4 | and adjust exponent 2108 1.1 mrg #endif 2109 1.1 mrg btst IMM (DBL_MANT_DIG-32-1),d0 2110 1.1 mrg bne Ldivdf$1 2111 1.1 mrg bra 1b 2112 1.1 mrg 2113 1.1 mrg Ldivdf$b$den: 2114 1.1 mrg movel IMM (1),d5 2115 1.1 mrg andl d6,d2 2116 1.1 mrg 1: addl d3,d3 | shift b left until bit 20 is set 2117 1.1 mrg addxl d2,d2 2118 1.1 mrg #ifndef __mcoldfire__ 2119 1.1 mrg subw IMM (1),d5 | and adjust exponent 2120 1.1 mrg #else 2121 1.1 mrg subql IMM (1),d5 | and adjust exponent 2122 1.1 mrg #endif 2123 1.1 mrg btst IMM (DBL_MANT_DIG-32-1),d2 2124 1.1 mrg bne Ldivdf$2 2125 1.1 mrg bra 1b 2126 1.1 mrg 2127 1.1 mrg Lround$exit: 2128 1.1 mrg | This is a common exit point for __muldf3 and __divdf3. When they enter 2129 1.1 mrg | this point the sign of the result is in d7, the result in d0-d1, normalized 2130 1.1 mrg | so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4. 2131 1.1 mrg 2132 1.1 mrg | First check for underlow in the exponent: 2133 1.1 mrg #ifndef __mcoldfire__ 2134 1.1 mrg cmpw IMM (-DBL_MANT_DIG-1),d4 2135 1.1 mrg #else 2136 1.1 mrg cmpl IMM (-DBL_MANT_DIG-1),d4 2137 1.1 mrg #endif 2138 1.1 mrg blt Ld$underflow 2139 1.1 mrg | It could happen that the exponent is less than 1, in which case the 2140 1.1 mrg | number is denormalized. In this case we shift right and adjust the 2141 1.1 mrg | exponent until it becomes 1 or the fraction is zero (in the latter case 2142 1.1 mrg | we signal underflow and return zero). 2143 1.1 mrg movel d7,a0 | 2144 1.1 mrg movel IMM (0),d6 | use d6-d7 to collect bits flushed right 2145 1.1 mrg movel d6,d7 | use d6-d7 to collect bits flushed right 2146 1.1 mrg #ifndef __mcoldfire__ 2147 1.1 mrg cmpw IMM (1),d4 | if the exponent is less than 1 we 2148 1.1 mrg #else 2149 1.1 mrg cmpl IMM (1),d4 | if the exponent is less than 1 we 2150 1.1 mrg #endif 2151 1.1 mrg bge 2f | have to shift right (denormalize) 2152 1.1 mrg 1: 2153 1.1 mrg #ifndef __mcoldfire__ 2154 1.1 mrg addw IMM (1),d4 | adjust the exponent 2155 1.1 mrg lsrl IMM (1),d0 | shift right once 2156 1.1 mrg roxrl IMM (1),d1 | 2157 1.1 mrg roxrl IMM (1),d2 | 2158 1.1 mrg roxrl IMM (1),d3 | 2159 1.1 mrg roxrl IMM (1),d6 | 2160 1.1 mrg roxrl IMM (1),d7 | 2161 1.1 mrg cmpw IMM (1),d4 | is the exponent 1 already? 2162 1.1 mrg #else 2163 1.1 mrg addl IMM (1),d4 | adjust the exponent 2164 1.1 mrg lsrl IMM (1),d7 2165 1.1 mrg btst IMM (0),d6 2166 1.1 mrg beq 13f 2167 1.1 mrg bset IMM (31),d7 2168 1.1 mrg 13: lsrl IMM (1),d6 2169 1.1 mrg btst IMM (0),d3 2170 1.1 mrg beq 14f 2171 1.1 mrg bset IMM (31),d6 2172 1.1 mrg 14: lsrl IMM (1),d3 2173 1.1 mrg btst IMM (0),d2 2174 1.1 mrg beq 10f 2175 1.1 mrg bset IMM (31),d3 2176 1.1 mrg 10: lsrl IMM (1),d2 2177 1.1 mrg btst IMM (0),d1 2178 1.1 mrg beq 11f 2179 1.1 mrg bset IMM (31),d2 2180 1.1 mrg 11: lsrl IMM (1),d1 2181 1.1 mrg btst IMM (0),d0 2182 1.1 mrg beq 12f 2183 1.1 mrg bset IMM (31),d1 2184 1.1 mrg 12: lsrl IMM (1),d0 2185 1.1 mrg cmpl IMM (1),d4 | is the exponent 1 already? 2186 1.1 mrg #endif 2187 1.1 mrg beq 2f | if not loop back 2188 1.1 mrg bra 1b | 2189 1.1 mrg bra Ld$underflow | safety check, shouldn't execute ' 2190 1.1 mrg 2: orl d6,d2 | this is a trick so we don't lose ' 2191 1.1 mrg orl d7,d3 | the bits which were flushed right 2192 1.1 mrg movel a0,d7 | get back sign bit into d7 2193 1.1 mrg | Now call the rounding routine (which takes care of denormalized numbers): 2194 1.1 mrg lea pc@(Lround$0),a0 | to return from rounding routine 2195 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 2196 1.1 mrg #ifdef __mcoldfire__ 2197 1.1 mrg clrl d6 2198 1.1 mrg #endif 2199 1.1 mrg movew a1@(6),d6 | rounding mode in d6 2200 1.1 mrg beq Lround$to$nearest 2201 1.1 mrg #ifndef __mcoldfire__ 2202 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 2203 1.1 mrg #else 2204 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 2205 1.1 mrg #endif 2206 1.1 mrg bhi Lround$to$minus 2207 1.1 mrg blt Lround$to$zero 2208 1.1 mrg bra Lround$to$plus 2209 1.1 mrg Lround$0: 2210 1.1 mrg | Here we have a correctly rounded result (either normalized or denormalized). 2211 1.1 mrg 2212 1.1 mrg | Here we should have either a normalized number or a denormalized one, and 2213 1.1 mrg | the exponent is necessarily larger or equal to 1 (so we don't have to ' 2214 1.1 mrg | check again for underflow!). We have to check for overflow or for a 2215 1.1 mrg | denormalized number (which also signals underflow). 2216 1.1 mrg | Check for overflow (i.e., exponent >= 0x7ff). 2217 1.1 mrg #ifndef __mcoldfire__ 2218 1.1 mrg cmpw IMM (0x07ff),d4 2219 1.1 mrg #else 2220 1.1 mrg cmpl IMM (0x07ff),d4 2221 1.1 mrg #endif 2222 1.1 mrg bge Ld$overflow 2223 1.1 mrg | Now check for a denormalized number (exponent==0): 2224 1.1 mrg movew d4,d4 2225 1.1 mrg beq Ld$den 2226 1.1 mrg 1: 2227 1.1 mrg | Put back the exponents and sign and return. 2228 1.1 mrg #ifndef __mcoldfire__ 2229 1.1 mrg lslw IMM (4),d4 | exponent back to fourth byte 2230 1.1 mrg #else 2231 1.1 mrg lsll IMM (4),d4 | exponent back to fourth byte 2232 1.1 mrg #endif 2233 1.1 mrg bclr IMM (DBL_MANT_DIG-32-1),d0 2234 1.1 mrg swap d0 | and put back exponent 2235 1.1 mrg #ifndef __mcoldfire__ 2236 1.1 mrg orw d4,d0 | 2237 1.1 mrg #else 2238 1.1 mrg orl d4,d0 | 2239 1.1 mrg #endif 2240 1.1 mrg swap d0 | 2241 1.1 mrg orl d7,d0 | and sign also 2242 1.1 mrg 2243 1.1 mrg PICLEA SYM (_fpCCR),a0 2244 1.1 mrg movew IMM (0),a0@ 2245 1.1 mrg #ifndef __mcoldfire__ 2246 1.1 mrg moveml sp@+,d2-d7 2247 1.1 mrg #else 2248 1.1 mrg moveml sp@,d2-d7 2249 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2250 1.1 mrg | be adjusted here. 2251 1.1 mrg #endif 2252 1.1 mrg unlk a6 2253 1.1 mrg rts 2254 1.1 mrg 2255 1.1 mrg |============================================================================= 2256 1.1 mrg | __negdf2 2257 1.1 mrg |============================================================================= 2258 1.1 mrg 2259 1.1 mrg | double __negdf2(double, double); 2260 1.1 mrg FUNC(__negdf2) 2261 1.1 mrg SYM (__negdf2): 2262 1.1 mrg #ifndef __mcoldfire__ 2263 1.1 mrg link a6,IMM (0) 2264 1.1 mrg moveml d2-d7,sp@- 2265 1.1 mrg #else 2266 1.1 mrg link a6,IMM (-24) 2267 1.1 mrg moveml d2-d7,sp@ 2268 1.1 mrg #endif 2269 1.1 mrg moveq IMM (NEGATE),d5 2270 1.1 mrg movel a6@(8),d0 | get number to negate in d0-d1 2271 1.1 mrg movel a6@(12),d1 | 2272 1.1 mrg bchg IMM (31),d0 | negate 2273 1.1 mrg movel d0,d2 | make a positive copy (for the tests) 2274 1.1 mrg bclr IMM (31),d2 | 2275 1.1 mrg movel d2,d4 | check for zero 2276 1.1 mrg orl d1,d4 | 2277 1.1 mrg beq 2f | if zero (either sign) return +zero 2278 1.1 mrg cmpl IMM (0x7ff00000),d2 | compare to +INFINITY 2279 1.1 mrg blt 1f | if finite, return 2280 1.1 mrg bhi Ld$inop | if larger (fraction not zero) is NaN 2281 1.1 mrg tstl d1 | if d2 == 0x7ff00000 check d1 2282 1.1 mrg bne Ld$inop | 2283 1.1 mrg movel d0,d7 | else get sign and return INFINITY 2284 1.1 mrg andl IMM (0x80000000),d7 2285 1.1 mrg bra Ld$infty 2286 1.1 mrg 1: PICLEA SYM (_fpCCR),a0 2287 1.1 mrg movew IMM (0),a0@ 2288 1.1 mrg #ifndef __mcoldfire__ 2289 1.1 mrg moveml sp@+,d2-d7 2290 1.1 mrg #else 2291 1.1 mrg moveml sp@,d2-d7 2292 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2293 1.1 mrg | be adjusted here. 2294 1.1 mrg #endif 2295 1.1 mrg unlk a6 2296 1.1 mrg rts 2297 1.1 mrg 2: bclr IMM (31),d0 2298 1.1 mrg bra 1b 2299 1.1 mrg 2300 1.1 mrg |============================================================================= 2301 1.1 mrg | __cmpdf2 2302 1.1 mrg |============================================================================= 2303 1.1 mrg 2304 1.1 mrg GREATER = 1 2305 1.1 mrg LESS = -1 2306 1.1 mrg EQUAL = 0 2307 1.1 mrg 2308 1.1 mrg | int __cmpdf2_internal(double, double, int); 2309 1.1 mrg SYM (__cmpdf2_internal): 2310 1.1 mrg #ifndef __mcoldfire__ 2311 1.1 mrg link a6,IMM (0) 2312 1.1 mrg moveml d2-d7,sp@- | save registers 2313 1.1 mrg #else 2314 1.1 mrg link a6,IMM (-24) 2315 1.1 mrg moveml d2-d7,sp@ 2316 1.1 mrg #endif 2317 1.1 mrg moveq IMM (COMPARE),d5 2318 1.1 mrg movel a6@(8),d0 | get first operand 2319 1.1 mrg movel a6@(12),d1 | 2320 1.1 mrg movel a6@(16),d2 | get second operand 2321 1.1 mrg movel a6@(20),d3 | 2322 1.1 mrg | First check if a and/or b are (+/-) zero and in that case clear 2323 1.1 mrg | the sign bit. 2324 1.1 mrg movel d0,d6 | copy signs into d6 (a) and d7(b) 2325 1.1 mrg bclr IMM (31),d0 | and clear signs in d0 and d2 2326 1.1 mrg movel d2,d7 | 2327 1.1 mrg bclr IMM (31),d2 | 2328 1.1 mrg cmpl IMM (0x7ff00000),d0 | check for a == NaN 2329 1.1 mrg bhi Lcmpd$inop | if d0 > 0x7ff00000, a is NaN 2330 1.1 mrg beq Lcmpdf$a$nf | if equal can be INFINITY, so check d1 2331 1.1 mrg movel d0,d4 | copy into d4 to test for zero 2332 1.1 mrg orl d1,d4 | 2333 1.1 mrg beq Lcmpdf$a$0 | 2334 1.1 mrg Lcmpdf$0: 2335 1.1 mrg cmpl IMM (0x7ff00000),d2 | check for b == NaN 2336 1.1 mrg bhi Lcmpd$inop | if d2 > 0x7ff00000, b is NaN 2337 1.1 mrg beq Lcmpdf$b$nf | if equal can be INFINITY, so check d3 2338 1.1 mrg movel d2,d4 | 2339 1.1 mrg orl d3,d4 | 2340 1.1 mrg beq Lcmpdf$b$0 | 2341 1.1 mrg Lcmpdf$1: 2342 1.1 mrg | Check the signs 2343 1.1 mrg eorl d6,d7 2344 1.1 mrg bpl 1f 2345 1.1 mrg | If the signs are not equal check if a >= 0 2346 1.1 mrg tstl d6 2347 1.1 mrg bpl Lcmpdf$a$gt$b | if (a >= 0 && b < 0) => a > b 2348 1.1 mrg bmi Lcmpdf$b$gt$a | if (a < 0 && b >= 0) => a < b 2349 1.1 mrg 1: 2350 1.1 mrg | If the signs are equal check for < 0 2351 1.1 mrg tstl d6 2352 1.1 mrg bpl 1f 2353 1.1 mrg | If both are negative exchange them 2354 1.1 mrg #ifndef __mcoldfire__ 2355 1.1 mrg exg d0,d2 2356 1.1 mrg exg d1,d3 2357 1.1 mrg #else 2358 1.1 mrg movel d0,d7 2359 1.1 mrg movel d2,d0 2360 1.1 mrg movel d7,d2 2361 1.1 mrg movel d1,d7 2362 1.1 mrg movel d3,d1 2363 1.1 mrg movel d7,d3 2364 1.1 mrg #endif 2365 1.1 mrg 1: 2366 1.1 mrg | Now that they are positive we just compare them as longs (does this also 2367 1.1 mrg | work for denormalized numbers?). 2368 1.1 mrg cmpl d0,d2 2369 1.1 mrg bhi Lcmpdf$b$gt$a | |b| > |a| 2370 1.1 mrg bne Lcmpdf$a$gt$b | |b| < |a| 2371 1.1 mrg | If we got here d0 == d2, so we compare d1 and d3. 2372 1.1 mrg cmpl d1,d3 2373 1.1 mrg bhi Lcmpdf$b$gt$a | |b| > |a| 2374 1.1 mrg bne Lcmpdf$a$gt$b | |b| < |a| 2375 1.1 mrg | If we got here a == b. 2376 1.1 mrg movel IMM (EQUAL),d0 2377 1.1 mrg #ifndef __mcoldfire__ 2378 1.1 mrg moveml sp@+,d2-d7 | put back the registers 2379 1.1 mrg #else 2380 1.1 mrg moveml sp@,d2-d7 2381 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2382 1.1 mrg | be adjusted here. 2383 1.1 mrg #endif 2384 1.1 mrg unlk a6 2385 1.1 mrg rts 2386 1.1 mrg Lcmpdf$a$gt$b: 2387 1.1 mrg movel IMM (GREATER),d0 2388 1.1 mrg #ifndef __mcoldfire__ 2389 1.1 mrg moveml sp@+,d2-d7 | put back the registers 2390 1.1 mrg #else 2391 1.1 mrg moveml sp@,d2-d7 2392 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2393 1.1 mrg | be adjusted here. 2394 1.1 mrg #endif 2395 1.1 mrg unlk a6 2396 1.1 mrg rts 2397 1.1 mrg Lcmpdf$b$gt$a: 2398 1.1 mrg movel IMM (LESS),d0 2399 1.1 mrg #ifndef __mcoldfire__ 2400 1.1 mrg moveml sp@+,d2-d7 | put back the registers 2401 1.1 mrg #else 2402 1.1 mrg moveml sp@,d2-d7 2403 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2404 1.1 mrg | be adjusted here. 2405 1.1 mrg #endif 2406 1.1 mrg unlk a6 2407 1.1 mrg rts 2408 1.1 mrg 2409 1.1 mrg Lcmpdf$a$0: 2410 1.1 mrg bclr IMM (31),d6 2411 1.1 mrg bra Lcmpdf$0 2412 1.1 mrg Lcmpdf$b$0: 2413 1.1 mrg bclr IMM (31),d7 2414 1.1 mrg bra Lcmpdf$1 2415 1.1 mrg 2416 1.1 mrg Lcmpdf$a$nf: 2417 1.1 mrg tstl d1 2418 1.1 mrg bne Ld$inop 2419 1.1 mrg bra Lcmpdf$0 2420 1.1 mrg 2421 1.1 mrg Lcmpdf$b$nf: 2422 1.1 mrg tstl d3 2423 1.1 mrg bne Ld$inop 2424 1.1 mrg bra Lcmpdf$1 2425 1.1 mrg 2426 1.1 mrg Lcmpd$inop: 2427 1.1 mrg movl a6@(24),d0 2428 1.1 mrg moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 2429 1.1 mrg moveq IMM (DOUBLE_FLOAT),d6 2430 1.1 mrg PICJUMP $_exception_handler 2431 1.1 mrg 2432 1.1 mrg | int __cmpdf2(double, double); 2433 1.1 mrg FUNC(__cmpdf2) 2434 1.1 mrg SYM (__cmpdf2): 2435 1.1 mrg link a6,IMM (0) 2436 1.1 mrg pea 1 2437 1.1 mrg movl a6@(20),sp@- 2438 1.1 mrg movl a6@(16),sp@- 2439 1.1 mrg movl a6@(12),sp@- 2440 1.1 mrg movl a6@(8),sp@- 2441 1.1 mrg PICCALL SYM (__cmpdf2_internal) 2442 1.1 mrg unlk a6 2443 1.1 mrg rts 2444 1.1 mrg 2445 1.1 mrg |============================================================================= 2446 1.1 mrg | rounding routines 2447 1.1 mrg |============================================================================= 2448 1.1 mrg 2449 1.1 mrg | The rounding routines expect the number to be normalized in registers 2450 1.1 mrg | d0-d1-d2-d3, with the exponent in register d4. They assume that the 2451 1.1 mrg | exponent is larger or equal to 1. They return a properly normalized number 2452 1.1 mrg | if possible, and a denormalized number otherwise. The exponent is returned 2453 1.1 mrg | in d4. 2454 1.1 mrg 2455 1.1 mrg Lround$to$nearest: 2456 1.1 mrg | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"): 2457 1.1 mrg | Here we assume that the exponent is not too small (this should be checked 2458 1.1 mrg | before entering the rounding routine), but the number could be denormalized. 2459 1.1 mrg 2460 1.1 mrg | Check for denormalized numbers: 2461 1.1 mrg 1: btst IMM (DBL_MANT_DIG-32),d0 2462 1.1 mrg bne 2f | if set the number is normalized 2463 1.1 mrg | Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent 2464 1.1 mrg | is one (remember that a denormalized number corresponds to an 2465 1.1 mrg | exponent of -D_BIAS+1). 2466 1.1 mrg #ifndef __mcoldfire__ 2467 1.1 mrg cmpw IMM (1),d4 | remember that the exponent is at least one 2468 1.1 mrg #else 2469 1.1 mrg cmpl IMM (1),d4 | remember that the exponent is at least one 2470 1.1 mrg #endif 2471 1.1 mrg beq 2f | an exponent of one means denormalized 2472 1.1 mrg addl d3,d3 | else shift and adjust the exponent 2473 1.1 mrg addxl d2,d2 | 2474 1.1 mrg addxl d1,d1 | 2475 1.1 mrg addxl d0,d0 | 2476 1.1 mrg #ifndef __mcoldfire__ 2477 1.1 mrg dbra d4,1b | 2478 1.1 mrg #else 2479 1.1 mrg subql IMM (1), d4 2480 1.1 mrg bpl 1b 2481 1.1 mrg #endif 2482 1.1 mrg 2: 2483 1.1 mrg | Now round: we do it as follows: after the shifting we can write the 2484 1.1 mrg | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2. 2485 1.1 mrg | If delta < 1, do nothing. If delta > 1, add 1 to f. 2486 1.1 mrg | If delta == 1, we make sure the rounded number will be even (odd?) 2487 1.1 mrg | (after shifting). 2488 1.1 mrg btst IMM (0),d1 | is delta < 1? 2489 1.1 mrg beq 2f | if so, do not do anything 2490 1.1 mrg orl d2,d3 | is delta == 1? 2491 1.1 mrg bne 1f | if so round to even 2492 1.1 mrg movel d1,d3 | 2493 1.1 mrg andl IMM (2),d3 | bit 1 is the last significant bit 2494 1.1 mrg movel IMM (0),d2 | 2495 1.1 mrg addl d3,d1 | 2496 1.1 mrg addxl d2,d0 | 2497 1.1 mrg bra 2f | 2498 1.1 mrg 1: movel IMM (1),d3 | else add 1 2499 1.1 mrg movel IMM (0),d2 | 2500 1.1 mrg addl d3,d1 | 2501 1.1 mrg addxl d2,d0 2502 1.1 mrg | Shift right once (because we used bit #DBL_MANT_DIG-32!). 2503 1.1 mrg 2: 2504 1.1 mrg #ifndef __mcoldfire__ 2505 1.1 mrg lsrl IMM (1),d0 2506 1.1 mrg roxrl IMM (1),d1 2507 1.1 mrg #else 2508 1.1 mrg lsrl IMM (1),d1 2509 1.1 mrg btst IMM (0),d0 2510 1.1 mrg beq 10f 2511 1.1 mrg bset IMM (31),d1 2512 1.1 mrg 10: lsrl IMM (1),d0 2513 1.1 mrg #endif 2514 1.1 mrg 2515 1.1 mrg | Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a 2516 1.1 mrg | 'fraction overflow' ...). 2517 1.1 mrg btst IMM (DBL_MANT_DIG-32),d0 2518 1.1 mrg beq 1f 2519 1.1 mrg #ifndef __mcoldfire__ 2520 1.1 mrg lsrl IMM (1),d0 2521 1.1 mrg roxrl IMM (1),d1 2522 1.1 mrg addw IMM (1),d4 2523 1.1 mrg #else 2524 1.1 mrg lsrl IMM (1),d1 2525 1.1 mrg btst IMM (0),d0 2526 1.1 mrg beq 10f 2527 1.1 mrg bset IMM (31),d1 2528 1.1 mrg 10: lsrl IMM (1),d0 2529 1.1 mrg addl IMM (1),d4 2530 1.1 mrg #endif 2531 1.1 mrg 1: 2532 1.1 mrg | If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we 2533 1.1 mrg | have to put the exponent to zero and return a denormalized number. 2534 1.1 mrg btst IMM (DBL_MANT_DIG-32-1),d0 2535 1.1 mrg beq 1f 2536 1.1 mrg jmp a0@ 2537 1.1 mrg 1: movel IMM (0),d4 2538 1.1 mrg jmp a0@ 2539 1.1 mrg 2540 1.1 mrg Lround$to$zero: 2541 1.1 mrg Lround$to$plus: 2542 1.1 mrg Lround$to$minus: 2543 1.1 mrg jmp a0@ 2544 1.1 mrg #endif /* L_double */ 2545 1.1 mrg 2546 1.1 mrg #ifdef L_float 2547 1.1 mrg 2548 1.1 mrg .globl SYM (_fpCCR) 2549 1.1 mrg .globl $_exception_handler 2550 1.1 mrg 2551 1.1 mrg QUIET_NaN = 0xffffffff 2552 1.1 mrg SIGNL_NaN = 0x7f800001 2553 1.1 mrg INFINITY = 0x7f800000 2554 1.1 mrg 2555 1.1 mrg F_MAX_EXP = 0xff 2556 1.1 mrg F_BIAS = 126 2557 1.1 mrg FLT_MAX_EXP = F_MAX_EXP - F_BIAS 2558 1.1 mrg FLT_MIN_EXP = 1 - F_BIAS 2559 1.1 mrg FLT_MANT_DIG = 24 2560 1.1 mrg 2561 1.1 mrg INEXACT_RESULT = 0x0001 2562 1.1 mrg UNDERFLOW = 0x0002 2563 1.1 mrg OVERFLOW = 0x0004 2564 1.1 mrg DIVIDE_BY_ZERO = 0x0008 2565 1.1 mrg INVALID_OPERATION = 0x0010 2566 1.1 mrg 2567 1.1 mrg SINGLE_FLOAT = 1 2568 1.1 mrg 2569 1.1 mrg NOOP = 0 2570 1.1 mrg ADD = 1 2571 1.1 mrg MULTIPLY = 2 2572 1.1 mrg DIVIDE = 3 2573 1.1 mrg NEGATE = 4 2574 1.1 mrg COMPARE = 5 2575 1.1 mrg EXTENDSFDF = 6 2576 1.1 mrg TRUNCDFSF = 7 2577 1.1 mrg 2578 1.1 mrg UNKNOWN = -1 2579 1.1 mrg ROUND_TO_NEAREST = 0 | round result to nearest representable value 2580 1.1 mrg ROUND_TO_ZERO = 1 | round result towards zero 2581 1.1 mrg ROUND_TO_PLUS = 2 | round result towards plus infinity 2582 1.1 mrg ROUND_TO_MINUS = 3 | round result towards minus infinity 2583 1.1 mrg 2584 1.1 mrg | Entry points: 2585 1.1 mrg 2586 1.1 mrg .globl SYM (__addsf3) 2587 1.1 mrg .globl SYM (__subsf3) 2588 1.1 mrg .globl SYM (__mulsf3) 2589 1.1 mrg .globl SYM (__divsf3) 2590 1.1 mrg .globl SYM (__negsf2) 2591 1.1 mrg .globl SYM (__cmpsf2) 2592 1.1 mrg .globl SYM (__cmpsf2_internal) 2593 1.1 mrg .hidden SYM (__cmpsf2_internal) 2594 1.1 mrg 2595 1.1 mrg | These are common routines to return and signal exceptions. 2596 1.1 mrg 2597 1.1 mrg .text 2598 1.1 mrg .even 2599 1.1 mrg 2600 1.1 mrg Lf$den: 2601 1.1 mrg | Return and signal a denormalized number 2602 1.1 mrg orl d7,d0 2603 1.1 mrg moveq IMM (INEXACT_RESULT+UNDERFLOW),d7 2604 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2605 1.1 mrg PICJUMP $_exception_handler 2606 1.1 mrg 2607 1.1 mrg Lf$infty: 2608 1.1 mrg Lf$overflow: 2609 1.1 mrg | Return a properly signed INFINITY and set the exception flags 2610 1.1 mrg movel IMM (INFINITY),d0 2611 1.1 mrg orl d7,d0 2612 1.1 mrg moveq IMM (INEXACT_RESULT+OVERFLOW),d7 2613 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2614 1.1 mrg PICJUMP $_exception_handler 2615 1.1 mrg 2616 1.1 mrg Lf$underflow: 2617 1.1 mrg | Return 0 and set the exception flags 2618 1.1 mrg moveq IMM (0),d0 2619 1.1 mrg moveq IMM (INEXACT_RESULT+UNDERFLOW),d7 2620 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2621 1.1 mrg PICJUMP $_exception_handler 2622 1.1 mrg 2623 1.1 mrg Lf$inop: 2624 1.1 mrg | Return a quiet NaN and set the exception flags 2625 1.1 mrg movel IMM (QUIET_NaN),d0 2626 1.1 mrg moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 2627 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2628 1.1 mrg PICJUMP $_exception_handler 2629 1.1 mrg 2630 1.1 mrg Lf$div$0: 2631 1.1 mrg | Return a properly signed INFINITY and set the exception flags 2632 1.1 mrg movel IMM (INFINITY),d0 2633 1.1 mrg orl d7,d0 2634 1.1 mrg moveq IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7 2635 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2636 1.1 mrg PICJUMP $_exception_handler 2637 1.1 mrg 2638 1.1 mrg |============================================================================= 2639 1.1 mrg |============================================================================= 2640 1.1 mrg | single precision routines 2641 1.1 mrg |============================================================================= 2642 1.1 mrg |============================================================================= 2643 1.1 mrg 2644 1.1 mrg | A single precision floating point number (float) has the format: 2645 1.1 mrg | 2646 1.1 mrg | struct _float { 2647 1.1 mrg | unsigned int sign : 1; /* sign bit */ 2648 1.1 mrg | unsigned int exponent : 8; /* exponent, shifted by 126 */ 2649 1.1 mrg | unsigned int fraction : 23; /* fraction */ 2650 1.1 mrg | } float; 2651 1.1 mrg | 2652 1.1 mrg | Thus sizeof(float) = 4 (32 bits). 2653 1.1 mrg | 2654 1.1 mrg | All the routines are callable from C programs, and return the result 2655 1.1 mrg | in the single register d0. They also preserve all registers except 2656 1.1 mrg | d0-d1 and a0-a1. 2657 1.1 mrg 2658 1.1 mrg |============================================================================= 2659 1.1 mrg | __subsf3 2660 1.1 mrg |============================================================================= 2661 1.1 mrg 2662 1.1 mrg | float __subsf3(float, float); 2663 1.1 mrg FUNC(__subsf3) 2664 1.1 mrg SYM (__subsf3): 2665 1.1 mrg bchg IMM (31),sp@(8) | change sign of second operand 2666 1.1 mrg | and fall through 2667 1.1 mrg |============================================================================= 2668 1.1 mrg | __addsf3 2669 1.1 mrg |============================================================================= 2670 1.1 mrg 2671 1.1 mrg | float __addsf3(float, float); 2672 1.1 mrg FUNC(__addsf3) 2673 1.1 mrg SYM (__addsf3): 2674 1.1 mrg #ifndef __mcoldfire__ 2675 1.1 mrg link a6,IMM (0) | everything will be done in registers 2676 1.1 mrg moveml d2-d7,sp@- | save all data registers but d0-d1 2677 1.1 mrg #else 2678 1.1 mrg link a6,IMM (-24) 2679 1.1 mrg moveml d2-d7,sp@ 2680 1.1 mrg #endif 2681 1.1 mrg movel a6@(8),d0 | get first operand 2682 1.1 mrg movel a6@(12),d1 | get second operand 2683 1.1 mrg movel d0,a0 | get d0's sign bit ' 2684 1.1 mrg addl d0,d0 | check and clear sign bit of a 2685 1.1 mrg beq Laddsf$b | if zero return second operand 2686 1.1 mrg movel d1,a1 | save b's sign bit ' 2687 1.1 mrg addl d1,d1 | get rid of sign bit 2688 1.1 mrg beq Laddsf$a | if zero return first operand 2689 1.1 mrg 2690 1.1 mrg | Get the exponents and check for denormalized and/or infinity. 2691 1.1 mrg 2692 1.1 mrg movel IMM (0x00ffffff),d4 | mask to get fraction 2693 1.1 mrg movel IMM (0x01000000),d5 | mask to put hidden bit back 2694 1.1 mrg 2695 1.1 mrg movel d0,d6 | save a to get exponent 2696 1.1 mrg andl d4,d0 | get fraction in d0 2697 1.1 mrg notl d4 | make d4 into a mask for the exponent 2698 1.1 mrg andl d4,d6 | get exponent in d6 2699 1.1 mrg beq Laddsf$a$den | branch if a is denormalized 2700 1.1 mrg cmpl d4,d6 | check for INFINITY or NaN 2701 1.1 mrg beq Laddsf$nf 2702 1.1 mrg swap d6 | put exponent into first word 2703 1.1 mrg orl d5,d0 | and put hidden bit back 2704 1.1 mrg Laddsf$1: 2705 1.1 mrg | Now we have a's exponent in d6 (second byte) and the mantissa in d0. ' 2706 1.1 mrg movel d1,d7 | get exponent in d7 2707 1.1 mrg andl d4,d7 | 2708 1.1 mrg beq Laddsf$b$den | branch if b is denormalized 2709 1.1 mrg cmpl d4,d7 | check for INFINITY or NaN 2710 1.1 mrg beq Laddsf$nf 2711 1.1 mrg swap d7 | put exponent into first word 2712 1.1 mrg notl d4 | make d4 into a mask for the fraction 2713 1.1 mrg andl d4,d1 | get fraction in d1 2714 1.1 mrg orl d5,d1 | and put hidden bit back 2715 1.1 mrg Laddsf$2: 2716 1.1 mrg | Now we have b's exponent in d7 (second byte) and the mantissa in d1. ' 2717 1.1 mrg 2718 1.1 mrg | Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we 2719 1.1 mrg | shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra 2720 1.1 mrg | bit). 2721 1.1 mrg 2722 1.1 mrg movel d1,d2 | move b to d2, since we want to use 2723 1.1 mrg | two registers to do the sum 2724 1.1 mrg movel IMM (0),d1 | and clear the new ones 2725 1.1 mrg movel d1,d3 | 2726 1.1 mrg 2727 1.1 mrg | Here we shift the numbers in registers d0 and d1 so the exponents are the 2728 1.1 mrg | same, and put the largest exponent in d6. Note that we are using two 2729 1.1 mrg | registers for each number (see the discussion by D. Knuth in "Seminumerical 2730 1.1 mrg | Algorithms"). 2731 1.1 mrg #ifndef __mcoldfire__ 2732 1.1 mrg cmpw d6,d7 | compare exponents 2733 1.1 mrg #else 2734 1.1 mrg cmpl d6,d7 | compare exponents 2735 1.1 mrg #endif 2736 1.1 mrg beq Laddsf$3 | if equal don't shift ' 2737 1.1 mrg bhi 5f | branch if second exponent largest 2738 1.1 mrg 1: 2739 1.1 mrg subl d6,d7 | keep the largest exponent 2740 1.1 mrg negl d7 2741 1.1 mrg #ifndef __mcoldfire__ 2742 1.1 mrg lsrw IMM (8),d7 | put difference in lower byte 2743 1.1 mrg #else 2744 1.1 mrg lsrl IMM (8),d7 | put difference in lower byte 2745 1.1 mrg #endif 2746 1.1 mrg | if difference is too large we don't shift (actually, we can just exit) ' 2747 1.1 mrg #ifndef __mcoldfire__ 2748 1.1 mrg cmpw IMM (FLT_MANT_DIG+2),d7 2749 1.1 mrg #else 2750 1.1 mrg cmpl IMM (FLT_MANT_DIG+2),d7 2751 1.1 mrg #endif 2752 1.1 mrg bge Laddsf$b$small 2753 1.1 mrg #ifndef __mcoldfire__ 2754 1.1 mrg cmpw IMM (16),d7 | if difference >= 16 swap 2755 1.1 mrg #else 2756 1.1 mrg cmpl IMM (16),d7 | if difference >= 16 swap 2757 1.1 mrg #endif 2758 1.1 mrg bge 4f 2759 1.1 mrg 2: 2760 1.1 mrg #ifndef __mcoldfire__ 2761 1.1 mrg subw IMM (1),d7 2762 1.1 mrg #else 2763 1.1 mrg subql IMM (1), d7 2764 1.1 mrg #endif 2765 1.1 mrg 3: 2766 1.1 mrg #ifndef __mcoldfire__ 2767 1.1 mrg lsrl IMM (1),d2 | shift right second operand 2768 1.1 mrg roxrl IMM (1),d3 2769 1.1 mrg dbra d7,3b 2770 1.1 mrg #else 2771 1.1 mrg lsrl IMM (1),d3 2772 1.1 mrg btst IMM (0),d2 2773 1.1 mrg beq 10f 2774 1.1 mrg bset IMM (31),d3 2775 1.1 mrg 10: lsrl IMM (1),d2 2776 1.1 mrg subql IMM (1), d7 2777 1.1 mrg bpl 3b 2778 1.1 mrg #endif 2779 1.1 mrg bra Laddsf$3 2780 1.1 mrg 4: 2781 1.1 mrg movew d2,d3 2782 1.1 mrg swap d3 2783 1.1 mrg movew d3,d2 2784 1.1 mrg swap d2 2785 1.1 mrg #ifndef __mcoldfire__ 2786 1.1 mrg subw IMM (16),d7 2787 1.1 mrg #else 2788 1.1 mrg subl IMM (16),d7 2789 1.1 mrg #endif 2790 1.1 mrg bne 2b | if still more bits, go back to normal case 2791 1.1 mrg bra Laddsf$3 2792 1.1 mrg 5: 2793 1.1 mrg #ifndef __mcoldfire__ 2794 1.1 mrg exg d6,d7 | exchange the exponents 2795 1.1 mrg #else 2796 1.1 mrg eorl d6,d7 2797 1.1 mrg eorl d7,d6 2798 1.1 mrg eorl d6,d7 2799 1.1 mrg #endif 2800 1.1 mrg subl d6,d7 | keep the largest exponent 2801 1.1 mrg negl d7 | 2802 1.1 mrg #ifndef __mcoldfire__ 2803 1.1 mrg lsrw IMM (8),d7 | put difference in lower byte 2804 1.1 mrg #else 2805 1.1 mrg lsrl IMM (8),d7 | put difference in lower byte 2806 1.1 mrg #endif 2807 1.1 mrg | if difference is too large we don't shift (and exit!) ' 2808 1.1 mrg #ifndef __mcoldfire__ 2809 1.1 mrg cmpw IMM (FLT_MANT_DIG+2),d7 2810 1.1 mrg #else 2811 1.1 mrg cmpl IMM (FLT_MANT_DIG+2),d7 2812 1.1 mrg #endif 2813 1.1 mrg bge Laddsf$a$small 2814 1.1 mrg #ifndef __mcoldfire__ 2815 1.1 mrg cmpw IMM (16),d7 | if difference >= 16 swap 2816 1.1 mrg #else 2817 1.1 mrg cmpl IMM (16),d7 | if difference >= 16 swap 2818 1.1 mrg #endif 2819 1.1 mrg bge 8f 2820 1.1 mrg 6: 2821 1.1 mrg #ifndef __mcoldfire__ 2822 1.1 mrg subw IMM (1),d7 2823 1.1 mrg #else 2824 1.1 mrg subl IMM (1),d7 2825 1.1 mrg #endif 2826 1.1 mrg 7: 2827 1.1 mrg #ifndef __mcoldfire__ 2828 1.1 mrg lsrl IMM (1),d0 | shift right first operand 2829 1.1 mrg roxrl IMM (1),d1 2830 1.1 mrg dbra d7,7b 2831 1.1 mrg #else 2832 1.1 mrg lsrl IMM (1),d1 2833 1.1 mrg btst IMM (0),d0 2834 1.1 mrg beq 10f 2835 1.1 mrg bset IMM (31),d1 2836 1.1 mrg 10: lsrl IMM (1),d0 2837 1.1 mrg subql IMM (1),d7 2838 1.1 mrg bpl 7b 2839 1.1 mrg #endif 2840 1.1 mrg bra Laddsf$3 2841 1.1 mrg 8: 2842 1.1 mrg movew d0,d1 2843 1.1 mrg swap d1 2844 1.1 mrg movew d1,d0 2845 1.1 mrg swap d0 2846 1.1 mrg #ifndef __mcoldfire__ 2847 1.1 mrg subw IMM (16),d7 2848 1.1 mrg #else 2849 1.1 mrg subl IMM (16),d7 2850 1.1 mrg #endif 2851 1.1 mrg bne 6b | if still more bits, go back to normal case 2852 1.1 mrg | otherwise we fall through 2853 1.1 mrg 2854 1.1 mrg | Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the 2855 1.1 mrg | signs are stored in a0 and a1). 2856 1.1 mrg 2857 1.1 mrg Laddsf$3: 2858 1.1 mrg | Here we have to decide whether to add or subtract the numbers 2859 1.1 mrg #ifndef __mcoldfire__ 2860 1.1 mrg exg d6,a0 | get signs back 2861 1.1 mrg exg d7,a1 | and save the exponents 2862 1.1 mrg #else 2863 1.1 mrg movel d6,d4 2864 1.1 mrg movel a0,d6 2865 1.1 mrg movel d4,a0 2866 1.1 mrg movel d7,d4 2867 1.1 mrg movel a1,d7 2868 1.1 mrg movel d4,a1 2869 1.1 mrg #endif 2870 1.1 mrg eorl d6,d7 | combine sign bits 2871 1.1 mrg bmi Lsubsf$0 | if negative a and b have opposite 2872 1.1 mrg | sign so we actually subtract the 2873 1.1 mrg | numbers 2874 1.1 mrg 2875 1.1 mrg | Here we have both positive or both negative 2876 1.1 mrg #ifndef __mcoldfire__ 2877 1.1 mrg exg d6,a0 | now we have the exponent in d6 2878 1.1 mrg #else 2879 1.1 mrg movel d6,d4 2880 1.1 mrg movel a0,d6 2881 1.1 mrg movel d4,a0 2882 1.1 mrg #endif 2883 1.1 mrg movel a0,d7 | and sign in d7 2884 1.1 mrg andl IMM (0x80000000),d7 2885 1.1 mrg | Here we do the addition. 2886 1.1 mrg addl d3,d1 2887 1.1 mrg addxl d2,d0 2888 1.1 mrg | Note: now we have d2, d3, d4 and d5 to play with! 2889 1.1 mrg 2890 1.1 mrg | Put the exponent, in the first byte, in d2, to use the "standard" rounding 2891 1.1 mrg | routines: 2892 1.1 mrg movel d6,d2 2893 1.1 mrg #ifndef __mcoldfire__ 2894 1.1 mrg lsrw IMM (8),d2 2895 1.1 mrg #else 2896 1.1 mrg lsrl IMM (8),d2 2897 1.1 mrg #endif 2898 1.1 mrg 2899 1.1 mrg | Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider 2900 1.1 mrg | the case of denormalized numbers in the rounding routine itself). 2901 1.1 mrg | As in the addition (not in the subtraction!) we could have set 2902 1.1 mrg | one more bit we check this: 2903 1.1 mrg btst IMM (FLT_MANT_DIG+1),d0 2904 1.1 mrg beq 1f 2905 1.1 mrg #ifndef __mcoldfire__ 2906 1.1 mrg lsrl IMM (1),d0 2907 1.1 mrg roxrl IMM (1),d1 2908 1.1 mrg #else 2909 1.1 mrg lsrl IMM (1),d1 2910 1.1 mrg btst IMM (0),d0 2911 1.1 mrg beq 10f 2912 1.1 mrg bset IMM (31),d1 2913 1.1 mrg 10: lsrl IMM (1),d0 2914 1.1 mrg #endif 2915 1.1 mrg addl IMM (1),d2 2916 1.1 mrg 1: 2917 1.1 mrg lea pc@(Laddsf$4),a0 | to return from rounding routine 2918 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 2919 1.1 mrg #ifdef __mcoldfire__ 2920 1.1 mrg clrl d6 2921 1.1 mrg #endif 2922 1.1 mrg movew a1@(6),d6 | rounding mode in d6 2923 1.1 mrg beq Lround$to$nearest 2924 1.1 mrg #ifndef __mcoldfire__ 2925 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 2926 1.1 mrg #else 2927 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 2928 1.1 mrg #endif 2929 1.1 mrg bhi Lround$to$minus 2930 1.1 mrg blt Lround$to$zero 2931 1.1 mrg bra Lround$to$plus 2932 1.1 mrg Laddsf$4: 2933 1.1 mrg | Put back the exponent, but check for overflow. 2934 1.1 mrg #ifndef __mcoldfire__ 2935 1.1 mrg cmpw IMM (0xff),d2 2936 1.1 mrg #else 2937 1.1 mrg cmpl IMM (0xff),d2 2938 1.1 mrg #endif 2939 1.1 mrg bhi 1f 2940 1.1 mrg bclr IMM (FLT_MANT_DIG-1),d0 2941 1.1 mrg #ifndef __mcoldfire__ 2942 1.1 mrg lslw IMM (7),d2 2943 1.1 mrg #else 2944 1.1 mrg lsll IMM (7),d2 2945 1.1 mrg #endif 2946 1.1 mrg swap d2 2947 1.1 mrg orl d2,d0 2948 1.1 mrg bra Laddsf$ret 2949 1.1 mrg 1: 2950 1.1 mrg moveq IMM (ADD),d5 2951 1.1 mrg bra Lf$overflow 2952 1.1 mrg 2953 1.1 mrg Lsubsf$0: 2954 1.1 mrg | We are here if a > 0 and b < 0 (sign bits cleared). 2955 1.1 mrg | Here we do the subtraction. 2956 1.1 mrg movel d6,d7 | put sign in d7 2957 1.1 mrg andl IMM (0x80000000),d7 2958 1.1 mrg 2959 1.1 mrg subl d3,d1 | result in d0-d1 2960 1.1 mrg subxl d2,d0 | 2961 1.1 mrg beq Laddsf$ret | if zero just exit 2962 1.1 mrg bpl 1f | if positive skip the following 2963 1.1 mrg bchg IMM (31),d7 | change sign bit in d7 2964 1.1 mrg negl d1 2965 1.1 mrg negxl d0 2966 1.1 mrg 1: 2967 1.1 mrg #ifndef __mcoldfire__ 2968 1.1 mrg exg d2,a0 | now we have the exponent in d2 2969 1.1 mrg lsrw IMM (8),d2 | put it in the first byte 2970 1.1 mrg #else 2971 1.1 mrg movel d2,d4 2972 1.1 mrg movel a0,d2 2973 1.1 mrg movel d4,a0 2974 1.1 mrg lsrl IMM (8),d2 | put it in the first byte 2975 1.1 mrg #endif 2976 1.1 mrg 2977 1.1 mrg | Now d0-d1 is positive and the sign bit is in d7. 2978 1.1 mrg 2979 1.1 mrg | Note that we do not have to normalize, since in the subtraction bit 2980 1.1 mrg | #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by 2981 1.1 mrg | the rounding routines themselves. 2982 1.1 mrg lea pc@(Lsubsf$1),a0 | to return from rounding routine 2983 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 2984 1.1 mrg #ifdef __mcoldfire__ 2985 1.1 mrg clrl d6 2986 1.1 mrg #endif 2987 1.1 mrg movew a1@(6),d6 | rounding mode in d6 2988 1.1 mrg beq Lround$to$nearest 2989 1.1 mrg #ifndef __mcoldfire__ 2990 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 2991 1.1 mrg #else 2992 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 2993 1.1 mrg #endif 2994 1.1 mrg bhi Lround$to$minus 2995 1.1 mrg blt Lround$to$zero 2996 1.1 mrg bra Lround$to$plus 2997 1.1 mrg Lsubsf$1: 2998 1.1 mrg | Put back the exponent (we can't have overflow!). ' 2999 1.1 mrg bclr IMM (FLT_MANT_DIG-1),d0 3000 1.1 mrg #ifndef __mcoldfire__ 3001 1.1 mrg lslw IMM (7),d2 3002 1.1 mrg #else 3003 1.1 mrg lsll IMM (7),d2 3004 1.1 mrg #endif 3005 1.1 mrg swap d2 3006 1.1 mrg orl d2,d0 3007 1.1 mrg bra Laddsf$ret 3008 1.1 mrg 3009 1.1 mrg | If one of the numbers was too small (difference of exponents >= 3010 1.1 mrg | FLT_MANT_DIG+2) we return the other (and now we don't have to ' 3011 1.1 mrg | check for finiteness or zero). 3012 1.1 mrg Laddsf$a$small: 3013 1.1 mrg movel a6@(12),d0 3014 1.1 mrg PICLEA SYM (_fpCCR),a0 3015 1.1 mrg movew IMM (0),a0@ 3016 1.1 mrg #ifndef __mcoldfire__ 3017 1.1 mrg moveml sp@+,d2-d7 | restore data registers 3018 1.1 mrg #else 3019 1.1 mrg moveml sp@,d2-d7 3020 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3021 1.1 mrg | be adjusted here. 3022 1.1 mrg #endif 3023 1.1 mrg unlk a6 | and return 3024 1.1 mrg rts 3025 1.1 mrg 3026 1.1 mrg Laddsf$b$small: 3027 1.1 mrg movel a6@(8),d0 3028 1.1 mrg PICLEA SYM (_fpCCR),a0 3029 1.1 mrg movew IMM (0),a0@ 3030 1.1 mrg #ifndef __mcoldfire__ 3031 1.1 mrg moveml sp@+,d2-d7 | restore data registers 3032 1.1 mrg #else 3033 1.1 mrg moveml sp@,d2-d7 3034 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3035 1.1 mrg | be adjusted here. 3036 1.1 mrg #endif 3037 1.1 mrg unlk a6 | and return 3038 1.1 mrg rts 3039 1.1 mrg 3040 1.1 mrg | If the numbers are denormalized remember to put exponent equal to 1. 3041 1.1 mrg 3042 1.1 mrg Laddsf$a$den: 3043 1.1 mrg movel d5,d6 | d5 contains 0x01000000 3044 1.1 mrg swap d6 3045 1.1 mrg bra Laddsf$1 3046 1.1 mrg 3047 1.1 mrg Laddsf$b$den: 3048 1.1 mrg movel d5,d7 3049 1.1 mrg swap d7 3050 1.1 mrg notl d4 | make d4 into a mask for the fraction 3051 1.1 mrg | (this was not executed after the jump) 3052 1.1 mrg bra Laddsf$2 3053 1.1 mrg 3054 1.1 mrg | The rest is mainly code for the different results which can be 3055 1.1 mrg | returned (checking always for +/-INFINITY and NaN). 3056 1.1 mrg 3057 1.1 mrg Laddsf$b: 3058 1.1 mrg | Return b (if a is zero). 3059 1.1 mrg movel a6@(12),d0 3060 1.1 mrg cmpl IMM (0x80000000),d0 | Check if b is -0 3061 1.1 mrg bne 1f 3062 1.1 mrg movel a0,d7 3063 1.1 mrg andl IMM (0x80000000),d7 | Use the sign of a 3064 1.1 mrg clrl d0 3065 1.1 mrg bra Laddsf$ret 3066 1.1 mrg Laddsf$a: 3067 1.1 mrg | Return a (if b is zero). 3068 1.1 mrg movel a6@(8),d0 3069 1.1 mrg 1: 3070 1.1 mrg moveq IMM (ADD),d5 3071 1.1 mrg | We have to check for NaN and +/-infty. 3072 1.1 mrg movel d0,d7 3073 1.1 mrg andl IMM (0x80000000),d7 | put sign in d7 3074 1.1 mrg bclr IMM (31),d0 | clear sign 3075 1.1 mrg cmpl IMM (INFINITY),d0 | check for infty or NaN 3076 1.1 mrg bge 2f 3077 1.1 mrg movel d0,d0 | check for zero (we do this because we don't ' 3078 1.1 mrg bne Laddsf$ret | want to return -0 by mistake 3079 1.1 mrg bclr IMM (31),d7 | if zero be sure to clear sign 3080 1.1 mrg bra Laddsf$ret | if everything OK just return 3081 1.1 mrg 2: 3082 1.1 mrg | The value to be returned is either +/-infty or NaN 3083 1.1 mrg andl IMM (0x007fffff),d0 | check for NaN 3084 1.1 mrg bne Lf$inop | if mantissa not zero is NaN 3085 1.1 mrg bra Lf$infty 3086 1.1 mrg 3087 1.1 mrg Laddsf$ret: 3088 1.1 mrg | Normal exit (a and b nonzero, result is not NaN nor +/-infty). 3089 1.1 mrg | We have to clear the exception flags (just the exception type). 3090 1.1 mrg PICLEA SYM (_fpCCR),a0 3091 1.1 mrg movew IMM (0),a0@ 3092 1.1 mrg orl d7,d0 | put sign bit 3093 1.1 mrg #ifndef __mcoldfire__ 3094 1.1 mrg moveml sp@+,d2-d7 | restore data registers 3095 1.1 mrg #else 3096 1.1 mrg moveml sp@,d2-d7 3097 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3098 1.1 mrg | be adjusted here. 3099 1.1 mrg #endif 3100 1.1 mrg unlk a6 | and return 3101 1.1 mrg rts 3102 1.1 mrg 3103 1.1 mrg Laddsf$ret$den: 3104 1.1 mrg | Return a denormalized number (for addition we don't signal underflow) ' 3105 1.1 mrg lsrl IMM (1),d0 | remember to shift right back once 3106 1.1 mrg bra Laddsf$ret | and return 3107 1.1 mrg 3108 1.1 mrg | Note: when adding two floats of the same sign if either one is 3109 1.1 mrg | NaN we return NaN without regard to whether the other is finite or 3110 1.1 mrg | not. When subtracting them (i.e., when adding two numbers of 3111 1.1 mrg | opposite signs) things are more complicated: if both are INFINITY 3112 1.1 mrg | we return NaN, if only one is INFINITY and the other is NaN we return 3113 1.1 mrg | NaN, but if it is finite we return INFINITY with the corresponding sign. 3114 1.1 mrg 3115 1.1 mrg Laddsf$nf: 3116 1.1 mrg moveq IMM (ADD),d5 3117 1.1 mrg | This could be faster but it is not worth the effort, since it is not 3118 1.1 mrg | executed very often. We sacrifice speed for clarity here. 3119 1.1 mrg movel a6@(8),d0 | get the numbers back (remember that we 3120 1.1 mrg movel a6@(12),d1 | did some processing already) 3121 1.1 mrg movel IMM (INFINITY),d4 | useful constant (INFINITY) 3122 1.1 mrg movel d0,d2 | save sign bits 3123 1.9 mrg movel d0,d7 | into d7 as well as we may need the sign 3124 1.9 mrg | bit before jumping to LfSinfty 3125 1.1 mrg movel d1,d3 3126 1.1 mrg bclr IMM (31),d0 | clear sign bits 3127 1.1 mrg bclr IMM (31),d1 3128 1.1 mrg | We know that one of them is either NaN of +/-INFINITY 3129 1.1 mrg | Check for NaN (if either one is NaN return NaN) 3130 1.1 mrg cmpl d4,d0 | check first a (d0) 3131 1.1 mrg bhi Lf$inop 3132 1.1 mrg cmpl d4,d1 | check now b (d1) 3133 1.1 mrg bhi Lf$inop 3134 1.1 mrg | Now comes the check for +/-INFINITY. We know that both are (maybe not 3135 1.1 mrg | finite) numbers, but we have to check if both are infinite whether we 3136 1.1 mrg | are adding or subtracting them. 3137 1.1 mrg eorl d3,d2 | to check sign bits 3138 1.1 mrg bmi 1f 3139 1.1 mrg andl IMM (0x80000000),d7 | get (common) sign bit 3140 1.1 mrg bra Lf$infty 3141 1.1 mrg 1: 3142 1.1 mrg | We know one (or both) are infinite, so we test for equality between the 3143 1.1 mrg | two numbers (if they are equal they have to be infinite both, so we 3144 1.1 mrg | return NaN). 3145 1.1 mrg cmpl d1,d0 | are both infinite? 3146 1.1 mrg beq Lf$inop | if so return NaN 3147 1.1 mrg 3148 1.1 mrg andl IMM (0x80000000),d7 | get a's sign bit ' 3149 1.1 mrg cmpl d4,d0 | test now for infinity 3150 1.1 mrg beq Lf$infty | if a is INFINITY return with this sign 3151 1.1 mrg bchg IMM (31),d7 | else we know b is INFINITY and has 3152 1.1 mrg bra Lf$infty | the opposite sign 3153 1.1 mrg 3154 1.1 mrg |============================================================================= 3155 1.1 mrg | __mulsf3 3156 1.1 mrg |============================================================================= 3157 1.1 mrg 3158 1.1 mrg | float __mulsf3(float, float); 3159 1.1 mrg FUNC(__mulsf3) 3160 1.1 mrg SYM (__mulsf3): 3161 1.1 mrg #ifndef __mcoldfire__ 3162 1.1 mrg link a6,IMM (0) 3163 1.1 mrg moveml d2-d7,sp@- 3164 1.1 mrg #else 3165 1.1 mrg link a6,IMM (-24) 3166 1.1 mrg moveml d2-d7,sp@ 3167 1.1 mrg #endif 3168 1.1 mrg movel a6@(8),d0 | get a into d0 3169 1.1 mrg movel a6@(12),d1 | and b into d1 3170 1.1 mrg movel d0,d7 | d7 will hold the sign of the product 3171 1.1 mrg eorl d1,d7 | 3172 1.1 mrg andl IMM (0x80000000),d7 3173 1.1 mrg movel IMM (INFINITY),d6 | useful constant (+INFINITY) 3174 1.1 mrg movel d6,d5 | another (mask for fraction) 3175 1.1 mrg notl d5 | 3176 1.1 mrg movel IMM (0x00800000),d4 | this is to put hidden bit back 3177 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 3178 1.1 mrg movel d0,d2 | 3179 1.1 mrg beq Lmulsf$a$0 | branch if a is zero 3180 1.1 mrg bclr IMM (31),d1 | get rid of b's sign bit ' 3181 1.1 mrg movel d1,d3 | 3182 1.1 mrg beq Lmulsf$b$0 | branch if b is zero 3183 1.1 mrg cmpl d6,d0 | is a big? 3184 1.1 mrg bhi Lmulsf$inop | if a is NaN return NaN 3185 1.1 mrg beq Lmulsf$inf | if a is INFINITY we have to check b 3186 1.1 mrg cmpl d6,d1 | now compare b with INFINITY 3187 1.1 mrg bhi Lmulsf$inop | is b NaN? 3188 1.1 mrg beq Lmulsf$overflow | is b INFINITY? 3189 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 3190 1.1 mrg | Now we get the exponents into d2 and d3. 3191 1.1 mrg andl d6,d2 | and isolate exponent in d2 3192 1.1 mrg beq Lmulsf$a$den | if exponent is zero we have a denormalized 3193 1.1 mrg andl d5,d0 | and isolate fraction 3194 1.1 mrg orl d4,d0 | and put hidden bit back 3195 1.1 mrg swap d2 | I like exponents in the first byte 3196 1.1 mrg #ifndef __mcoldfire__ 3197 1.1 mrg lsrw IMM (7),d2 | 3198 1.1 mrg #else 3199 1.1 mrg lsrl IMM (7),d2 | 3200 1.1 mrg #endif 3201 1.1 mrg Lmulsf$1: | number 3202 1.1 mrg andl d6,d3 | 3203 1.1 mrg beq Lmulsf$b$den | 3204 1.1 mrg andl d5,d1 | 3205 1.1 mrg orl d4,d1 | 3206 1.1 mrg swap d3 | 3207 1.1 mrg #ifndef __mcoldfire__ 3208 1.1 mrg lsrw IMM (7),d3 | 3209 1.1 mrg #else 3210 1.1 mrg lsrl IMM (7),d3 | 3211 1.1 mrg #endif 3212 1.1 mrg Lmulsf$2: | 3213 1.1 mrg #ifndef __mcoldfire__ 3214 1.1 mrg addw d3,d2 | add exponents 3215 1.1 mrg subw IMM (F_BIAS+1),d2 | and subtract bias (plus one) 3216 1.1 mrg #else 3217 1.1 mrg addl d3,d2 | add exponents 3218 1.1 mrg subl IMM (F_BIAS+1),d2 | and subtract bias (plus one) 3219 1.1 mrg #endif 3220 1.1 mrg 3221 1.1 mrg | We are now ready to do the multiplication. The situation is as follows: 3222 1.1 mrg | both a and b have bit FLT_MANT_DIG-1 set (even if they were 3223 1.1 mrg | denormalized to start with!), which means that in the product 3224 1.1 mrg | bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the 3225 1.1 mrg | high long) is set. 3226 1.1 mrg 3227 1.1 mrg | To do the multiplication let us move the number a little bit around ... 3228 1.1 mrg movel d1,d6 | second operand in d6 3229 1.1 mrg movel d0,d5 | first operand in d4-d5 3230 1.1 mrg movel IMM (0),d4 3231 1.1 mrg movel d4,d1 | the sums will go in d0-d1 3232 1.1 mrg movel d4,d0 3233 1.1 mrg 3234 1.1 mrg | now bit FLT_MANT_DIG-1 becomes bit 31: 3235 1.1 mrg lsll IMM (31-FLT_MANT_DIG+1),d6 3236 1.1 mrg 3237 1.1 mrg | Start the loop (we loop #FLT_MANT_DIG times): 3238 1.1 mrg moveq IMM (FLT_MANT_DIG-1),d3 3239 1.1 mrg 1: addl d1,d1 | shift sum 3240 1.1 mrg addxl d0,d0 3241 1.1 mrg lsll IMM (1),d6 | get bit bn 3242 1.1 mrg bcc 2f | if not set skip sum 3243 1.1 mrg addl d5,d1 | add a 3244 1.1 mrg addxl d4,d0 3245 1.1 mrg 2: 3246 1.1 mrg #ifndef __mcoldfire__ 3247 1.1 mrg dbf d3,1b | loop back 3248 1.1 mrg #else 3249 1.1 mrg subql IMM (1),d3 3250 1.1 mrg bpl 1b 3251 1.1 mrg #endif 3252 1.1 mrg 3253 1.1 mrg | Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG 3254 1.1 mrg | (mod 32) of d0 set. The first thing to do now is to normalize it so bit 3255 1.1 mrg | FLT_MANT_DIG is set (to do the rounding). 3256 1.1 mrg #ifndef __mcoldfire__ 3257 1.1 mrg rorl IMM (6),d1 3258 1.1 mrg swap d1 3259 1.1 mrg movew d1,d3 3260 1.1 mrg andw IMM (0x03ff),d3 3261 1.1 mrg andw IMM (0xfd00),d1 3262 1.1 mrg #else 3263 1.1 mrg movel d1,d3 3264 1.1 mrg lsll IMM (8),d1 3265 1.1 mrg addl d1,d1 3266 1.1 mrg addl d1,d1 3267 1.1 mrg moveq IMM (22),d5 3268 1.1 mrg lsrl d5,d3 3269 1.1 mrg orl d3,d1 3270 1.1 mrg andl IMM (0xfffffd00),d1 3271 1.1 mrg #endif 3272 1.1 mrg lsll IMM (8),d0 3273 1.1 mrg addl d0,d0 3274 1.1 mrg addl d0,d0 3275 1.1 mrg #ifndef __mcoldfire__ 3276 1.1 mrg orw d3,d0 3277 1.1 mrg #else 3278 1.1 mrg orl d3,d0 3279 1.1 mrg #endif 3280 1.1 mrg 3281 1.1 mrg moveq IMM (MULTIPLY),d5 3282 1.1 mrg 3283 1.1 mrg btst IMM (FLT_MANT_DIG+1),d0 3284 1.1 mrg beq Lround$exit 3285 1.1 mrg #ifndef __mcoldfire__ 3286 1.1 mrg lsrl IMM (1),d0 3287 1.1 mrg roxrl IMM (1),d1 3288 1.1 mrg addw IMM (1),d2 3289 1.1 mrg #else 3290 1.1 mrg lsrl IMM (1),d1 3291 1.1 mrg btst IMM (0),d0 3292 1.1 mrg beq 10f 3293 1.1 mrg bset IMM (31),d1 3294 1.1 mrg 10: lsrl IMM (1),d0 3295 1.1 mrg addql IMM (1),d2 3296 1.1 mrg #endif 3297 1.1 mrg bra Lround$exit 3298 1.1 mrg 3299 1.1 mrg Lmulsf$inop: 3300 1.1 mrg moveq IMM (MULTIPLY),d5 3301 1.1 mrg bra Lf$inop 3302 1.1 mrg 3303 1.1 mrg Lmulsf$overflow: 3304 1.1 mrg moveq IMM (MULTIPLY),d5 3305 1.1 mrg bra Lf$overflow 3306 1.1 mrg 3307 1.1 mrg Lmulsf$inf: 3308 1.1 mrg moveq IMM (MULTIPLY),d5 3309 1.1 mrg | If either is NaN return NaN; else both are (maybe infinite) numbers, so 3310 1.1 mrg | return INFINITY with the correct sign (which is in d7). 3311 1.1 mrg cmpl d6,d1 | is b NaN? 3312 1.1 mrg bhi Lf$inop | if so return NaN 3313 1.1 mrg bra Lf$overflow | else return +/-INFINITY 3314 1.1 mrg 3315 1.1 mrg | If either number is zero return zero, unless the other is +/-INFINITY, 3316 1.1 mrg | or NaN, in which case we return NaN. 3317 1.1 mrg Lmulsf$b$0: 3318 1.1 mrg | Here d1 (==b) is zero. 3319 1.1 mrg movel a6@(8),d1 | get a again to check for non-finiteness 3320 1.1 mrg bra 1f 3321 1.1 mrg Lmulsf$a$0: 3322 1.1 mrg movel a6@(12),d1 | get b again to check for non-finiteness 3323 1.1 mrg 1: bclr IMM (31),d1 | clear sign bit 3324 1.1 mrg cmpl IMM (INFINITY),d1 | and check for a large exponent 3325 1.1 mrg bge Lf$inop | if b is +/-INFINITY or NaN return NaN 3326 1.1 mrg movel d7,d0 | else return signed zero 3327 1.1 mrg PICLEA SYM (_fpCCR),a0 | 3328 1.1 mrg movew IMM (0),a0@ | 3329 1.1 mrg #ifndef __mcoldfire__ 3330 1.1 mrg moveml sp@+,d2-d7 | 3331 1.1 mrg #else 3332 1.1 mrg moveml sp@,d2-d7 3333 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3334 1.1 mrg | be adjusted here. 3335 1.1 mrg #endif 3336 1.1 mrg unlk a6 | 3337 1.1 mrg rts | 3338 1.1 mrg 3339 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 3340 1.1 mrg | hidden bit back into the fraction; instead we shift left until bit 23 3341 1.1 mrg | (the hidden bit) is set, adjusting the exponent accordingly. We do this 3342 1.1 mrg | to ensure that the product of the fractions is close to 1. 3343 1.1 mrg Lmulsf$a$den: 3344 1.1 mrg movel IMM (1),d2 3345 1.1 mrg andl d5,d0 3346 1.1 mrg 1: addl d0,d0 | shift a left (until bit 23 is set) 3347 1.1 mrg #ifndef __mcoldfire__ 3348 1.1 mrg subw IMM (1),d2 | and adjust exponent 3349 1.1 mrg #else 3350 1.1 mrg subql IMM (1),d2 | and adjust exponent 3351 1.1 mrg #endif 3352 1.1 mrg btst IMM (FLT_MANT_DIG-1),d0 3353 1.1 mrg bne Lmulsf$1 | 3354 1.1 mrg bra 1b | else loop back 3355 1.1 mrg 3356 1.1 mrg Lmulsf$b$den: 3357 1.1 mrg movel IMM (1),d3 3358 1.1 mrg andl d5,d1 3359 1.1 mrg 1: addl d1,d1 | shift b left until bit 23 is set 3360 1.1 mrg #ifndef __mcoldfire__ 3361 1.1 mrg subw IMM (1),d3 | and adjust exponent 3362 1.1 mrg #else 3363 1.1 mrg subql IMM (1),d3 | and adjust exponent 3364 1.1 mrg #endif 3365 1.1 mrg btst IMM (FLT_MANT_DIG-1),d1 3366 1.1 mrg bne Lmulsf$2 | 3367 1.1 mrg bra 1b | else loop back 3368 1.1 mrg 3369 1.1 mrg |============================================================================= 3370 1.1 mrg | __divsf3 3371 1.1 mrg |============================================================================= 3372 1.1 mrg 3373 1.1 mrg | float __divsf3(float, float); 3374 1.1 mrg FUNC(__divsf3) 3375 1.1 mrg SYM (__divsf3): 3376 1.1 mrg #ifndef __mcoldfire__ 3377 1.1 mrg link a6,IMM (0) 3378 1.1 mrg moveml d2-d7,sp@- 3379 1.1 mrg #else 3380 1.1 mrg link a6,IMM (-24) 3381 1.1 mrg moveml d2-d7,sp@ 3382 1.1 mrg #endif 3383 1.1 mrg movel a6@(8),d0 | get a into d0 3384 1.1 mrg movel a6@(12),d1 | and b into d1 3385 1.1 mrg movel d0,d7 | d7 will hold the sign of the result 3386 1.1 mrg eorl d1,d7 | 3387 1.1 mrg andl IMM (0x80000000),d7 | 3388 1.1 mrg movel IMM (INFINITY),d6 | useful constant (+INFINITY) 3389 1.1 mrg movel d6,d5 | another (mask for fraction) 3390 1.1 mrg notl d5 | 3391 1.1 mrg movel IMM (0x00800000),d4 | this is to put hidden bit back 3392 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 3393 1.1 mrg movel d0,d2 | 3394 1.1 mrg beq Ldivsf$a$0 | branch if a is zero 3395 1.1 mrg bclr IMM (31),d1 | get rid of b's sign bit ' 3396 1.1 mrg movel d1,d3 | 3397 1.1 mrg beq Ldivsf$b$0 | branch if b is zero 3398 1.1 mrg cmpl d6,d0 | is a big? 3399 1.1 mrg bhi Ldivsf$inop | if a is NaN return NaN 3400 1.1 mrg beq Ldivsf$inf | if a is INFINITY we have to check b 3401 1.1 mrg cmpl d6,d1 | now compare b with INFINITY 3402 1.1 mrg bhi Ldivsf$inop | if b is NaN return NaN 3403 1.1 mrg beq Ldivsf$underflow 3404 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 3405 1.1 mrg | Now we get the exponents into d2 and d3 and normalize the numbers to 3406 1.1 mrg | ensure that the ratio of the fractions is close to 1. We do this by 3407 1.1 mrg | making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set. 3408 1.1 mrg andl d6,d2 | and isolate exponent in d2 3409 1.1 mrg beq Ldivsf$a$den | if exponent is zero we have a denormalized 3410 1.1 mrg andl d5,d0 | and isolate fraction 3411 1.1 mrg orl d4,d0 | and put hidden bit back 3412 1.1 mrg swap d2 | I like exponents in the first byte 3413 1.1 mrg #ifndef __mcoldfire__ 3414 1.1 mrg lsrw IMM (7),d2 | 3415 1.1 mrg #else 3416 1.1 mrg lsrl IMM (7),d2 | 3417 1.1 mrg #endif 3418 1.1 mrg Ldivsf$1: | 3419 1.1 mrg andl d6,d3 | 3420 1.1 mrg beq Ldivsf$b$den | 3421 1.1 mrg andl d5,d1 | 3422 1.1 mrg orl d4,d1 | 3423 1.1 mrg swap d3 | 3424 1.1 mrg #ifndef __mcoldfire__ 3425 1.1 mrg lsrw IMM (7),d3 | 3426 1.1 mrg #else 3427 1.1 mrg lsrl IMM (7),d3 | 3428 1.1 mrg #endif 3429 1.1 mrg Ldivsf$2: | 3430 1.1 mrg #ifndef __mcoldfire__ 3431 1.1 mrg subw d3,d2 | subtract exponents 3432 1.1 mrg addw IMM (F_BIAS),d2 | and add bias 3433 1.1 mrg #else 3434 1.1 mrg subl d3,d2 | subtract exponents 3435 1.1 mrg addl IMM (F_BIAS),d2 | and add bias 3436 1.1 mrg #endif 3437 1.1 mrg 3438 1.1 mrg | We are now ready to do the division. We have prepared things in such a way 3439 1.1 mrg | that the ratio of the fractions will be less than 2 but greater than 1/2. 3440 1.1 mrg | At this point the registers in use are: 3441 1.1 mrg | d0 holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1) 3442 1.1 mrg | d1 holds b (second operand, bit FLT_MANT_DIG=1) 3443 1.1 mrg | d2 holds the difference of the exponents, corrected by the bias 3444 1.1 mrg | d7 holds the sign of the ratio 3445 1.1 mrg | d4, d5, d6 hold some constants 3446 1.1 mrg movel d7,a0 | d6-d7 will hold the ratio of the fractions 3447 1.1 mrg movel IMM (0),d6 | 3448 1.1 mrg movel d6,d7 3449 1.1 mrg 3450 1.1 mrg moveq IMM (FLT_MANT_DIG+1),d3 3451 1.1 mrg 1: cmpl d0,d1 | is a < b? 3452 1.1 mrg bhi 2f | 3453 1.1 mrg bset d3,d6 | set a bit in d6 3454 1.1 mrg subl d1,d0 | if a >= b a <-- a-b 3455 1.1 mrg beq 3f | if a is zero, exit 3456 1.1 mrg 2: addl d0,d0 | multiply a by 2 3457 1.1 mrg #ifndef __mcoldfire__ 3458 1.1 mrg dbra d3,1b 3459 1.1 mrg #else 3460 1.1 mrg subql IMM (1),d3 3461 1.1 mrg bpl 1b 3462 1.1 mrg #endif 3463 1.1 mrg 3464 1.1 mrg | Now we keep going to set the sticky bit ... 3465 1.1 mrg moveq IMM (FLT_MANT_DIG),d3 3466 1.1 mrg 1: cmpl d0,d1 3467 1.1 mrg ble 2f 3468 1.1 mrg addl d0,d0 3469 1.1 mrg #ifndef __mcoldfire__ 3470 1.1 mrg dbra d3,1b 3471 1.1 mrg #else 3472 1.1 mrg subql IMM(1),d3 3473 1.1 mrg bpl 1b 3474 1.1 mrg #endif 3475 1.1 mrg movel IMM (0),d1 3476 1.1 mrg bra 3f 3477 1.1 mrg 2: movel IMM (0),d1 3478 1.1 mrg #ifndef __mcoldfire__ 3479 1.1 mrg subw IMM (FLT_MANT_DIG),d3 3480 1.1 mrg addw IMM (31),d3 3481 1.1 mrg #else 3482 1.1 mrg subl IMM (FLT_MANT_DIG),d3 3483 1.1 mrg addl IMM (31),d3 3484 1.1 mrg #endif 3485 1.1 mrg bset d3,d1 3486 1.1 mrg 3: 3487 1.1 mrg movel d6,d0 | put the ratio in d0-d1 3488 1.1 mrg movel a0,d7 | get sign back 3489 1.1 mrg 3490 1.1 mrg | Because of the normalization we did before we are guaranteed that 3491 1.1 mrg | d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set, 3492 1.1 mrg | bit 25 could be set, and if it is not set then bit 24 is necessarily set. 3493 1.1 mrg btst IMM (FLT_MANT_DIG+1),d0 3494 1.1 mrg beq 1f | if it is not set, then bit 24 is set 3495 1.1 mrg lsrl IMM (1),d0 | 3496 1.1 mrg #ifndef __mcoldfire__ 3497 1.1 mrg addw IMM (1),d2 | 3498 1.1 mrg #else 3499 1.1 mrg addl IMM (1),d2 | 3500 1.1 mrg #endif 3501 1.1 mrg 1: 3502 1.1 mrg | Now round, check for over- and underflow, and exit. 3503 1.1 mrg moveq IMM (DIVIDE),d5 3504 1.1 mrg bra Lround$exit 3505 1.1 mrg 3506 1.1 mrg Ldivsf$inop: 3507 1.1 mrg moveq IMM (DIVIDE),d5 3508 1.1 mrg bra Lf$inop 3509 1.1 mrg 3510 1.1 mrg Ldivsf$overflow: 3511 1.1 mrg moveq IMM (DIVIDE),d5 3512 1.1 mrg bra Lf$overflow 3513 1.1 mrg 3514 1.1 mrg Ldivsf$underflow: 3515 1.1 mrg moveq IMM (DIVIDE),d5 3516 1.1 mrg bra Lf$underflow 3517 1.1 mrg 3518 1.1 mrg Ldivsf$a$0: 3519 1.1 mrg moveq IMM (DIVIDE),d5 3520 1.1 mrg | If a is zero check to see whether b is zero also. In that case return 3521 1.1 mrg | NaN; then check if b is NaN, and return NaN also in that case. Else 3522 1.1 mrg | return a properly signed zero. 3523 1.1 mrg andl IMM (0x7fffffff),d1 | clear sign bit and test b 3524 1.1 mrg beq Lf$inop | if b is also zero return NaN 3525 1.1 mrg cmpl IMM (INFINITY),d1 | check for NaN 3526 1.1 mrg bhi Lf$inop | 3527 1.1 mrg movel d7,d0 | else return signed zero 3528 1.1 mrg PICLEA SYM (_fpCCR),a0 | 3529 1.1 mrg movew IMM (0),a0@ | 3530 1.1 mrg #ifndef __mcoldfire__ 3531 1.1 mrg moveml sp@+,d2-d7 | 3532 1.1 mrg #else 3533 1.1 mrg moveml sp@,d2-d7 | 3534 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3535 1.1 mrg | be adjusted here. 3536 1.1 mrg #endif 3537 1.1 mrg unlk a6 | 3538 1.1 mrg rts | 3539 1.1 mrg 3540 1.1 mrg Ldivsf$b$0: 3541 1.1 mrg moveq IMM (DIVIDE),d5 3542 1.1 mrg | If we got here a is not zero. Check if a is NaN; in that case return NaN, 3543 1.1 mrg | else return +/-INFINITY. Remember that a is in d0 with the sign bit 3544 1.1 mrg | cleared already. 3545 1.1 mrg cmpl IMM (INFINITY),d0 | compare d0 with INFINITY 3546 1.1 mrg bhi Lf$inop | if larger it is NaN 3547 1.1 mrg bra Lf$div$0 | else signal DIVIDE_BY_ZERO 3548 1.1 mrg 3549 1.1 mrg Ldivsf$inf: 3550 1.1 mrg moveq IMM (DIVIDE),d5 3551 1.1 mrg | If a is INFINITY we have to check b 3552 1.1 mrg cmpl IMM (INFINITY),d1 | compare b with INFINITY 3553 1.1 mrg bge Lf$inop | if b is NaN or INFINITY return NaN 3554 1.1 mrg bra Lf$overflow | else return overflow 3555 1.1 mrg 3556 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 3557 1.1 mrg | bit back into the fraction. 3558 1.1 mrg Ldivsf$a$den: 3559 1.1 mrg movel IMM (1),d2 3560 1.1 mrg andl d5,d0 3561 1.1 mrg 1: addl d0,d0 | shift a left until bit FLT_MANT_DIG-1 is set 3562 1.1 mrg #ifndef __mcoldfire__ 3563 1.1 mrg subw IMM (1),d2 | and adjust exponent 3564 1.1 mrg #else 3565 1.1 mrg subl IMM (1),d2 | and adjust exponent 3566 1.1 mrg #endif 3567 1.1 mrg btst IMM (FLT_MANT_DIG-1),d0 3568 1.1 mrg bne Ldivsf$1 3569 1.1 mrg bra 1b 3570 1.1 mrg 3571 1.1 mrg Ldivsf$b$den: 3572 1.1 mrg movel IMM (1),d3 3573 1.1 mrg andl d5,d1 3574 1.1 mrg 1: addl d1,d1 | shift b left until bit FLT_MANT_DIG is set 3575 1.1 mrg #ifndef __mcoldfire__ 3576 1.1 mrg subw IMM (1),d3 | and adjust exponent 3577 1.1 mrg #else 3578 1.1 mrg subl IMM (1),d3 | and adjust exponent 3579 1.1 mrg #endif 3580 1.1 mrg btst IMM (FLT_MANT_DIG-1),d1 3581 1.1 mrg bne Ldivsf$2 3582 1.1 mrg bra 1b 3583 1.1 mrg 3584 1.1 mrg Lround$exit: 3585 1.1 mrg | This is a common exit point for __mulsf3 and __divsf3. 3586 1.1 mrg 3587 1.1 mrg | First check for underlow in the exponent: 3588 1.1 mrg #ifndef __mcoldfire__ 3589 1.1 mrg cmpw IMM (-FLT_MANT_DIG-1),d2 3590 1.1 mrg #else 3591 1.1 mrg cmpl IMM (-FLT_MANT_DIG-1),d2 3592 1.1 mrg #endif 3593 1.1 mrg blt Lf$underflow 3594 1.1 mrg | It could happen that the exponent is less than 1, in which case the 3595 1.1 mrg | number is denormalized. In this case we shift right and adjust the 3596 1.1 mrg | exponent until it becomes 1 or the fraction is zero (in the latter case 3597 1.1 mrg | we signal underflow and return zero). 3598 1.1 mrg movel IMM (0),d6 | d6 is used temporarily 3599 1.1 mrg #ifndef __mcoldfire__ 3600 1.1 mrg cmpw IMM (1),d2 | if the exponent is less than 1 we 3601 1.1 mrg #else 3602 1.1 mrg cmpl IMM (1),d2 | if the exponent is less than 1 we 3603 1.1 mrg #endif 3604 1.1 mrg bge 2f | have to shift right (denormalize) 3605 1.1 mrg 1: 3606 1.1 mrg #ifndef __mcoldfire__ 3607 1.1 mrg addw IMM (1),d2 | adjust the exponent 3608 1.1 mrg lsrl IMM (1),d0 | shift right once 3609 1.1 mrg roxrl IMM (1),d1 | 3610 1.1 mrg roxrl IMM (1),d6 | d6 collect bits we would lose otherwise 3611 1.1 mrg cmpw IMM (1),d2 | is the exponent 1 already? 3612 1.1 mrg #else 3613 1.1 mrg addql IMM (1),d2 | adjust the exponent 3614 1.1 mrg lsrl IMM (1),d6 3615 1.1 mrg btst IMM (0),d1 3616 1.1 mrg beq 11f 3617 1.1 mrg bset IMM (31),d6 3618 1.1 mrg 11: lsrl IMM (1),d1 3619 1.1 mrg btst IMM (0),d0 3620 1.1 mrg beq 10f 3621 1.1 mrg bset IMM (31),d1 3622 1.1 mrg 10: lsrl IMM (1),d0 3623 1.1 mrg cmpl IMM (1),d2 | is the exponent 1 already? 3624 1.1 mrg #endif 3625 1.1 mrg beq 2f | if not loop back 3626 1.1 mrg bra 1b | 3627 1.1 mrg bra Lf$underflow | safety check, shouldn't execute ' 3628 1.1 mrg 2: orl d6,d1 | this is a trick so we don't lose ' 3629 1.1 mrg | the extra bits which were flushed right 3630 1.1 mrg | Now call the rounding routine (which takes care of denormalized numbers): 3631 1.1 mrg lea pc@(Lround$0),a0 | to return from rounding routine 3632 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 3633 1.1 mrg #ifdef __mcoldfire__ 3634 1.1 mrg clrl d6 3635 1.1 mrg #endif 3636 1.1 mrg movew a1@(6),d6 | rounding mode in d6 3637 1.1 mrg beq Lround$to$nearest 3638 1.1 mrg #ifndef __mcoldfire__ 3639 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 3640 1.1 mrg #else 3641 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 3642 1.1 mrg #endif 3643 1.1 mrg bhi Lround$to$minus 3644 1.1 mrg blt Lround$to$zero 3645 1.1 mrg bra Lround$to$plus 3646 1.1 mrg Lround$0: 3647 1.1 mrg | Here we have a correctly rounded result (either normalized or denormalized). 3648 1.1 mrg 3649 1.1 mrg | Here we should have either a normalized number or a denormalized one, and 3650 1.1 mrg | the exponent is necessarily larger or equal to 1 (so we don't have to ' 3651 1.1 mrg | check again for underflow!). We have to check for overflow or for a 3652 1.1 mrg | denormalized number (which also signals underflow). 3653 1.1 mrg | Check for overflow (i.e., exponent >= 255). 3654 1.1 mrg #ifndef __mcoldfire__ 3655 1.1 mrg cmpw IMM (0x00ff),d2 3656 1.1 mrg #else 3657 1.1 mrg cmpl IMM (0x00ff),d2 3658 1.1 mrg #endif 3659 1.1 mrg bge Lf$overflow 3660 1.1 mrg | Now check for a denormalized number (exponent==0). 3661 1.1 mrg movew d2,d2 3662 1.1 mrg beq Lf$den 3663 1.1 mrg 1: 3664 1.1 mrg | Put back the exponents and sign and return. 3665 1.1 mrg #ifndef __mcoldfire__ 3666 1.1 mrg lslw IMM (7),d2 | exponent back to fourth byte 3667 1.1 mrg #else 3668 1.1 mrg lsll IMM (7),d2 | exponent back to fourth byte 3669 1.1 mrg #endif 3670 1.1 mrg bclr IMM (FLT_MANT_DIG-1),d0 3671 1.1 mrg swap d0 | and put back exponent 3672 1.1 mrg #ifndef __mcoldfire__ 3673 1.1 mrg orw d2,d0 | 3674 1.1 mrg #else 3675 1.1 mrg orl d2,d0 3676 1.1 mrg #endif 3677 1.1 mrg swap d0 | 3678 1.1 mrg orl d7,d0 | and sign also 3679 1.1 mrg 3680 1.1 mrg PICLEA SYM (_fpCCR),a0 3681 1.1 mrg movew IMM (0),a0@ 3682 1.1 mrg #ifndef __mcoldfire__ 3683 1.1 mrg moveml sp@+,d2-d7 3684 1.1 mrg #else 3685 1.1 mrg moveml sp@,d2-d7 3686 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3687 1.1 mrg | be adjusted here. 3688 1.1 mrg #endif 3689 1.1 mrg unlk a6 3690 1.1 mrg rts 3691 1.1 mrg 3692 1.1 mrg |============================================================================= 3693 1.1 mrg | __negsf2 3694 1.1 mrg |============================================================================= 3695 1.1 mrg 3696 1.1 mrg | This is trivial and could be shorter if we didn't bother checking for NaN ' 3697 1.1 mrg | and +/-INFINITY. 3698 1.1 mrg 3699 1.1 mrg | float __negsf2(float); 3700 1.1 mrg FUNC(__negsf2) 3701 1.1 mrg SYM (__negsf2): 3702 1.1 mrg #ifndef __mcoldfire__ 3703 1.1 mrg link a6,IMM (0) 3704 1.1 mrg moveml d2-d7,sp@- 3705 1.1 mrg #else 3706 1.1 mrg link a6,IMM (-24) 3707 1.1 mrg moveml d2-d7,sp@ 3708 1.1 mrg #endif 3709 1.1 mrg moveq IMM (NEGATE),d5 3710 1.1 mrg movel a6@(8),d0 | get number to negate in d0 3711 1.1 mrg bchg IMM (31),d0 | negate 3712 1.1 mrg movel d0,d1 | make a positive copy 3713 1.1 mrg bclr IMM (31),d1 | 3714 1.1 mrg tstl d1 | check for zero 3715 1.1 mrg beq 2f | if zero (either sign) return +zero 3716 1.1 mrg cmpl IMM (INFINITY),d1 | compare to +INFINITY 3717 1.1 mrg blt 1f | 3718 1.1 mrg bhi Lf$inop | if larger (fraction not zero) is NaN 3719 1.1 mrg movel d0,d7 | else get sign and return INFINITY 3720 1.1 mrg andl IMM (0x80000000),d7 3721 1.1 mrg bra Lf$infty 3722 1.1 mrg 1: PICLEA SYM (_fpCCR),a0 3723 1.1 mrg movew IMM (0),a0@ 3724 1.1 mrg #ifndef __mcoldfire__ 3725 1.1 mrg moveml sp@+,d2-d7 3726 1.1 mrg #else 3727 1.1 mrg moveml sp@,d2-d7 3728 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3729 1.1 mrg | be adjusted here. 3730 1.1 mrg #endif 3731 1.1 mrg unlk a6 3732 1.1 mrg rts 3733 1.1 mrg 2: bclr IMM (31),d0 3734 1.1 mrg bra 1b 3735 1.1 mrg 3736 1.1 mrg |============================================================================= 3737 1.1 mrg | __cmpsf2 3738 1.1 mrg |============================================================================= 3739 1.1 mrg 3740 1.1 mrg GREATER = 1 3741 1.1 mrg LESS = -1 3742 1.1 mrg EQUAL = 0 3743 1.1 mrg 3744 1.1 mrg | int __cmpsf2_internal(float, float, int); 3745 1.1 mrg SYM (__cmpsf2_internal): 3746 1.1 mrg #ifndef __mcoldfire__ 3747 1.1 mrg link a6,IMM (0) 3748 1.1 mrg moveml d2-d7,sp@- | save registers 3749 1.1 mrg #else 3750 1.1 mrg link a6,IMM (-24) 3751 1.1 mrg moveml d2-d7,sp@ 3752 1.1 mrg #endif 3753 1.1 mrg moveq IMM (COMPARE),d5 3754 1.1 mrg movel a6@(8),d0 | get first operand 3755 1.1 mrg movel a6@(12),d1 | get second operand 3756 1.1 mrg | Check if either is NaN, and in that case return garbage and signal 3757 1.1 mrg | INVALID_OPERATION. Check also if either is zero, and clear the signs 3758 1.1 mrg | if necessary. 3759 1.1 mrg movel d0,d6 3760 1.1 mrg andl IMM (0x7fffffff),d0 3761 1.1 mrg beq Lcmpsf$a$0 3762 1.1 mrg cmpl IMM (0x7f800000),d0 3763 1.1 mrg bhi Lcmpf$inop 3764 1.1 mrg Lcmpsf$1: 3765 1.1 mrg movel d1,d7 3766 1.1 mrg andl IMM (0x7fffffff),d1 3767 1.1 mrg beq Lcmpsf$b$0 3768 1.1 mrg cmpl IMM (0x7f800000),d1 3769 1.1 mrg bhi Lcmpf$inop 3770 1.1 mrg Lcmpsf$2: 3771 1.1 mrg | Check the signs 3772 1.1 mrg eorl d6,d7 3773 1.1 mrg bpl 1f 3774 1.1 mrg | If the signs are not equal check if a >= 0 3775 1.1 mrg tstl d6 3776 1.1 mrg bpl Lcmpsf$a$gt$b | if (a >= 0 && b < 0) => a > b 3777 1.1 mrg bmi Lcmpsf$b$gt$a | if (a < 0 && b >= 0) => a < b 3778 1.1 mrg 1: 3779 1.1 mrg | If the signs are equal check for < 0 3780 1.1 mrg tstl d6 3781 1.1 mrg bpl 1f 3782 1.1 mrg | If both are negative exchange them 3783 1.1 mrg #ifndef __mcoldfire__ 3784 1.1 mrg exg d0,d1 3785 1.1 mrg #else 3786 1.1 mrg movel d0,d7 3787 1.1 mrg movel d1,d0 3788 1.1 mrg movel d7,d1 3789 1.1 mrg #endif 3790 1.1 mrg 1: 3791 1.1 mrg | Now that they are positive we just compare them as longs (does this also 3792 1.1 mrg | work for denormalized numbers?). 3793 1.1 mrg cmpl d0,d1 3794 1.1 mrg bhi Lcmpsf$b$gt$a | |b| > |a| 3795 1.1 mrg bne Lcmpsf$a$gt$b | |b| < |a| 3796 1.1 mrg | If we got here a == b. 3797 1.1 mrg movel IMM (EQUAL),d0 3798 1.1 mrg #ifndef __mcoldfire__ 3799 1.1 mrg moveml sp@+,d2-d7 | put back the registers 3800 1.1 mrg #else 3801 1.1 mrg moveml sp@,d2-d7 3802 1.1 mrg #endif 3803 1.1 mrg unlk a6 3804 1.1 mrg rts 3805 1.1 mrg Lcmpsf$a$gt$b: 3806 1.1 mrg movel IMM (GREATER),d0 3807 1.1 mrg #ifndef __mcoldfire__ 3808 1.1 mrg moveml sp@+,d2-d7 | put back the registers 3809 1.1 mrg #else 3810 1.1 mrg moveml sp@,d2-d7 3811 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3812 1.1 mrg | be adjusted here. 3813 1.1 mrg #endif 3814 1.1 mrg unlk a6 3815 1.1 mrg rts 3816 1.1 mrg Lcmpsf$b$gt$a: 3817 1.1 mrg movel IMM (LESS),d0 3818 1.1 mrg #ifndef __mcoldfire__ 3819 1.1 mrg moveml sp@+,d2-d7 | put back the registers 3820 1.1 mrg #else 3821 1.1 mrg moveml sp@,d2-d7 3822 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3823 1.1 mrg | be adjusted here. 3824 1.1 mrg #endif 3825 1.1 mrg unlk a6 3826 1.1 mrg rts 3827 1.1 mrg 3828 1.1 mrg Lcmpsf$a$0: 3829 1.1 mrg bclr IMM (31),d6 3830 1.1 mrg bra Lcmpsf$1 3831 1.1 mrg Lcmpsf$b$0: 3832 1.1 mrg bclr IMM (31),d7 3833 1.1 mrg bra Lcmpsf$2 3834 1.1 mrg 3835 1.1 mrg Lcmpf$inop: 3836 1.1 mrg movl a6@(16),d0 3837 1.1 mrg moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 3838 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 3839 1.1 mrg PICJUMP $_exception_handler 3840 1.1 mrg 3841 1.1 mrg | int __cmpsf2(float, float); 3842 1.1 mrg FUNC(__cmpsf2) 3843 1.1 mrg SYM (__cmpsf2): 3844 1.1 mrg link a6,IMM (0) 3845 1.1 mrg pea 1 3846 1.1 mrg movl a6@(12),sp@- 3847 1.1 mrg movl a6@(8),sp@- 3848 1.1 mrg PICCALL SYM (__cmpsf2_internal) 3849 1.1 mrg unlk a6 3850 1.1 mrg rts 3851 1.1 mrg 3852 1.1 mrg |============================================================================= 3853 1.1 mrg | rounding routines 3854 1.1 mrg |============================================================================= 3855 1.1 mrg 3856 1.1 mrg | The rounding routines expect the number to be normalized in registers 3857 1.1 mrg | d0-d1, with the exponent in register d2. They assume that the 3858 1.1 mrg | exponent is larger or equal to 1. They return a properly normalized number 3859 1.1 mrg | if possible, and a denormalized number otherwise. The exponent is returned 3860 1.1 mrg | in d2. 3861 1.1 mrg 3862 1.1 mrg Lround$to$nearest: 3863 1.1 mrg | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"): 3864 1.1 mrg | Here we assume that the exponent is not too small (this should be checked 3865 1.1 mrg | before entering the rounding routine), but the number could be denormalized. 3866 1.1 mrg 3867 1.1 mrg | Check for denormalized numbers: 3868 1.1 mrg 1: btst IMM (FLT_MANT_DIG),d0 3869 1.1 mrg bne 2f | if set the number is normalized 3870 1.1 mrg | Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent 3871 1.1 mrg | is one (remember that a denormalized number corresponds to an 3872 1.1 mrg | exponent of -F_BIAS+1). 3873 1.1 mrg #ifndef __mcoldfire__ 3874 1.1 mrg cmpw IMM (1),d2 | remember that the exponent is at least one 3875 1.1 mrg #else 3876 1.1 mrg cmpl IMM (1),d2 | remember that the exponent is at least one 3877 1.1 mrg #endif 3878 1.1 mrg beq 2f | an exponent of one means denormalized 3879 1.1 mrg addl d1,d1 | else shift and adjust the exponent 3880 1.1 mrg addxl d0,d0 | 3881 1.1 mrg #ifndef __mcoldfire__ 3882 1.1 mrg dbra d2,1b | 3883 1.1 mrg #else 3884 1.1 mrg subql IMM (1),d2 3885 1.1 mrg bpl 1b 3886 1.1 mrg #endif 3887 1.1 mrg 2: 3888 1.1 mrg | Now round: we do it as follows: after the shifting we can write the 3889 1.1 mrg | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2. 3890 1.1 mrg | If delta < 1, do nothing. If delta > 1, add 1 to f. 3891 1.1 mrg | If delta == 1, we make sure the rounded number will be even (odd?) 3892 1.1 mrg | (after shifting). 3893 1.1 mrg btst IMM (0),d0 | is delta < 1? 3894 1.1 mrg beq 2f | if so, do not do anything 3895 1.1 mrg tstl d1 | is delta == 1? 3896 1.1 mrg bne 1f | if so round to even 3897 1.1 mrg movel d0,d1 | 3898 1.1 mrg andl IMM (2),d1 | bit 1 is the last significant bit 3899 1.1 mrg addl d1,d0 | 3900 1.1 mrg bra 2f | 3901 1.1 mrg 1: movel IMM (1),d1 | else add 1 3902 1.1 mrg addl d1,d0 | 3903 1.1 mrg | Shift right once (because we used bit #FLT_MANT_DIG!). 3904 1.1 mrg 2: lsrl IMM (1),d0 3905 1.1 mrg | Now check again bit #FLT_MANT_DIG (rounding could have produced a 3906 1.1 mrg | 'fraction overflow' ...). 3907 1.1 mrg btst IMM (FLT_MANT_DIG),d0 3908 1.1 mrg beq 1f 3909 1.1 mrg lsrl IMM (1),d0 3910 1.1 mrg #ifndef __mcoldfire__ 3911 1.1 mrg addw IMM (1),d2 3912 1.1 mrg #else 3913 1.1 mrg addql IMM (1),d2 3914 1.1 mrg #endif 3915 1.1 mrg 1: 3916 1.1 mrg | If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we 3917 1.1 mrg | have to put the exponent to zero and return a denormalized number. 3918 1.1 mrg btst IMM (FLT_MANT_DIG-1),d0 3919 1.1 mrg beq 1f 3920 1.1 mrg jmp a0@ 3921 1.1 mrg 1: movel IMM (0),d2 3922 1.1 mrg jmp a0@ 3923 1.1 mrg 3924 1.1 mrg Lround$to$zero: 3925 1.1 mrg Lround$to$plus: 3926 1.1 mrg Lround$to$minus: 3927 1.1 mrg jmp a0@ 3928 1.1 mrg #endif /* L_float */ 3929 1.1 mrg 3930 1.1 mrg | gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2, 3931 1.1 mrg | __ledf2, __ltdf2 to all return the same value as a direct call to 3932 1.1 mrg | __cmpdf2 would. In this implementation, each of these routines 3933 1.1 mrg | simply calls __cmpdf2. It would be more efficient to give the 3934 1.1 mrg | __cmpdf2 routine several names, but separating them out will make it 3935 1.1 mrg | easier to write efficient versions of these routines someday. 3936 1.1 mrg | If the operands recompare unordered unordered __gtdf2 and __gedf2 return -1. 3937 1.1 mrg | The other routines return 1. 3938 1.1 mrg 3939 1.1 mrg #ifdef L_eqdf2 3940 1.1 mrg .text 3941 1.1 mrg FUNC(__eqdf2) 3942 1.1 mrg .globl SYM (__eqdf2) 3943 1.1 mrg SYM (__eqdf2): 3944 1.1 mrg link a6,IMM (0) 3945 1.1 mrg pea 1 3946 1.1 mrg movl a6@(20),sp@- 3947 1.1 mrg movl a6@(16),sp@- 3948 1.1 mrg movl a6@(12),sp@- 3949 1.1 mrg movl a6@(8),sp@- 3950 1.1 mrg PICCALL SYM (__cmpdf2_internal) 3951 1.1 mrg unlk a6 3952 1.1 mrg rts 3953 1.1 mrg #endif /* L_eqdf2 */ 3954 1.1 mrg 3955 1.1 mrg #ifdef L_nedf2 3956 1.1 mrg .text 3957 1.1 mrg FUNC(__nedf2) 3958 1.1 mrg .globl SYM (__nedf2) 3959 1.1 mrg SYM (__nedf2): 3960 1.1 mrg link a6,IMM (0) 3961 1.1 mrg pea 1 3962 1.1 mrg movl a6@(20),sp@- 3963 1.1 mrg movl a6@(16),sp@- 3964 1.1 mrg movl a6@(12),sp@- 3965 1.1 mrg movl a6@(8),sp@- 3966 1.1 mrg PICCALL SYM (__cmpdf2_internal) 3967 1.1 mrg unlk a6 3968 1.1 mrg rts 3969 1.1 mrg #endif /* L_nedf2 */ 3970 1.1 mrg 3971 1.1 mrg #ifdef L_gtdf2 3972 1.1 mrg .text 3973 1.1 mrg FUNC(__gtdf2) 3974 1.1 mrg .globl SYM (__gtdf2) 3975 1.1 mrg SYM (__gtdf2): 3976 1.1 mrg link a6,IMM (0) 3977 1.1 mrg pea -1 3978 1.1 mrg movl a6@(20),sp@- 3979 1.1 mrg movl a6@(16),sp@- 3980 1.1 mrg movl a6@(12),sp@- 3981 1.1 mrg movl a6@(8),sp@- 3982 1.1 mrg PICCALL SYM (__cmpdf2_internal) 3983 1.1 mrg unlk a6 3984 1.1 mrg rts 3985 1.1 mrg #endif /* L_gtdf2 */ 3986 1.1 mrg 3987 1.1 mrg #ifdef L_gedf2 3988 1.1 mrg .text 3989 1.1 mrg FUNC(__gedf2) 3990 1.1 mrg .globl SYM (__gedf2) 3991 1.1 mrg SYM (__gedf2): 3992 1.1 mrg link a6,IMM (0) 3993 1.1 mrg pea -1 3994 1.1 mrg movl a6@(20),sp@- 3995 1.1 mrg movl a6@(16),sp@- 3996 1.1 mrg movl a6@(12),sp@- 3997 1.1 mrg movl a6@(8),sp@- 3998 1.1 mrg PICCALL SYM (__cmpdf2_internal) 3999 1.1 mrg unlk a6 4000 1.1 mrg rts 4001 1.1 mrg #endif /* L_gedf2 */ 4002 1.1 mrg 4003 1.1 mrg #ifdef L_ltdf2 4004 1.1 mrg .text 4005 1.1 mrg FUNC(__ltdf2) 4006 1.1 mrg .globl SYM (__ltdf2) 4007 1.1 mrg SYM (__ltdf2): 4008 1.1 mrg link a6,IMM (0) 4009 1.1 mrg pea 1 4010 1.1 mrg movl a6@(20),sp@- 4011 1.1 mrg movl a6@(16),sp@- 4012 1.1 mrg movl a6@(12),sp@- 4013 1.1 mrg movl a6@(8),sp@- 4014 1.1 mrg PICCALL SYM (__cmpdf2_internal) 4015 1.1 mrg unlk a6 4016 1.1 mrg rts 4017 1.1 mrg #endif /* L_ltdf2 */ 4018 1.1 mrg 4019 1.1 mrg #ifdef L_ledf2 4020 1.1 mrg .text 4021 1.1 mrg FUNC(__ledf2) 4022 1.1 mrg .globl SYM (__ledf2) 4023 1.1 mrg SYM (__ledf2): 4024 1.1 mrg link a6,IMM (0) 4025 1.1 mrg pea 1 4026 1.1 mrg movl a6@(20),sp@- 4027 1.1 mrg movl a6@(16),sp@- 4028 1.1 mrg movl a6@(12),sp@- 4029 1.1 mrg movl a6@(8),sp@- 4030 1.1 mrg PICCALL SYM (__cmpdf2_internal) 4031 1.1 mrg unlk a6 4032 1.1 mrg rts 4033 1.1 mrg #endif /* L_ledf2 */ 4034 1.1 mrg 4035 1.1 mrg | The comments above about __eqdf2, et. al., also apply to __eqsf2, 4036 1.1 mrg | et. al., except that the latter call __cmpsf2 rather than __cmpdf2. 4037 1.1 mrg 4038 1.1 mrg #ifdef L_eqsf2 4039 1.1 mrg .text 4040 1.1 mrg FUNC(__eqsf2) 4041 1.1 mrg .globl SYM (__eqsf2) 4042 1.1 mrg SYM (__eqsf2): 4043 1.1 mrg link a6,IMM (0) 4044 1.1 mrg pea 1 4045 1.1 mrg movl a6@(12),sp@- 4046 1.1 mrg movl a6@(8),sp@- 4047 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4048 1.1 mrg unlk a6 4049 1.1 mrg rts 4050 1.1 mrg #endif /* L_eqsf2 */ 4051 1.1 mrg 4052 1.1 mrg #ifdef L_nesf2 4053 1.1 mrg .text 4054 1.1 mrg FUNC(__nesf2) 4055 1.1 mrg .globl SYM (__nesf2) 4056 1.1 mrg SYM (__nesf2): 4057 1.1 mrg link a6,IMM (0) 4058 1.1 mrg pea 1 4059 1.1 mrg movl a6@(12),sp@- 4060 1.1 mrg movl a6@(8),sp@- 4061 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4062 1.1 mrg unlk a6 4063 1.1 mrg rts 4064 1.1 mrg #endif /* L_nesf2 */ 4065 1.1 mrg 4066 1.1 mrg #ifdef L_gtsf2 4067 1.1 mrg .text 4068 1.1 mrg FUNC(__gtsf2) 4069 1.1 mrg .globl SYM (__gtsf2) 4070 1.1 mrg SYM (__gtsf2): 4071 1.1 mrg link a6,IMM (0) 4072 1.1 mrg pea -1 4073 1.1 mrg movl a6@(12),sp@- 4074 1.1 mrg movl a6@(8),sp@- 4075 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4076 1.1 mrg unlk a6 4077 1.1 mrg rts 4078 1.1 mrg #endif /* L_gtsf2 */ 4079 1.1 mrg 4080 1.1 mrg #ifdef L_gesf2 4081 1.1 mrg .text 4082 1.1 mrg FUNC(__gesf2) 4083 1.1 mrg .globl SYM (__gesf2) 4084 1.1 mrg SYM (__gesf2): 4085 1.1 mrg link a6,IMM (0) 4086 1.1 mrg pea -1 4087 1.1 mrg movl a6@(12),sp@- 4088 1.1 mrg movl a6@(8),sp@- 4089 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4090 1.1 mrg unlk a6 4091 1.1 mrg rts 4092 1.1 mrg #endif /* L_gesf2 */ 4093 1.1 mrg 4094 1.1 mrg #ifdef L_ltsf2 4095 1.1 mrg .text 4096 1.1 mrg FUNC(__ltsf2) 4097 1.1 mrg .globl SYM (__ltsf2) 4098 1.1 mrg SYM (__ltsf2): 4099 1.1 mrg link a6,IMM (0) 4100 1.1 mrg pea 1 4101 1.1 mrg movl a6@(12),sp@- 4102 1.1 mrg movl a6@(8),sp@- 4103 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4104 1.1 mrg unlk a6 4105 1.1 mrg rts 4106 1.1 mrg #endif /* L_ltsf2 */ 4107 1.1 mrg 4108 1.1 mrg #ifdef L_lesf2 4109 1.1 mrg .text 4110 1.1 mrg FUNC(__lesf2) 4111 1.1 mrg .globl SYM (__lesf2) 4112 1.1 mrg SYM (__lesf2): 4113 1.1 mrg link a6,IMM (0) 4114 1.1 mrg pea 1 4115 1.1 mrg movl a6@(12),sp@- 4116 1.1 mrg movl a6@(8),sp@- 4117 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4118 1.1 mrg unlk a6 4119 1.1 mrg rts 4120 1.1 mrg #endif /* L_lesf2 */ 4121 1.1 mrg 4122 1.1 mrg #if defined (__ELF__) && defined (__linux__) 4123 1.1 mrg /* Make stack non-executable for ELF linux targets. */ 4124 1.1 mrg .section .note.GNU-stack,"",@progbits 4125 1.1 mrg #endif 4126