1 1.1 mrg /* libgcc routines for 68000 w/o floating-point hardware. 2 1.11 mrg Copyright (C) 1994-2024 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.4 christos 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.4 christos 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.10 mrg .globl SYM (__mulsi3_internal) 439 1.10 mrg .hidden SYM (__mulsi3_internal) 440 1.1 mrg SYM (__mulsi3): 441 1.10 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.10 mrg .globl SYM (__udivsi3_internal) 465 1.10 mrg .hidden SYM (__udivsi3_internal) 466 1.1 mrg SYM (__udivsi3): 467 1.10 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.10 mrg .globl SYM (__divsi3_internal) 544 1.10 mrg .hidden SYM (__divsi3_internal) 545 1.1 mrg SYM (__divsi3): 546 1.10 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.10 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.10 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.10 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.10 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.10 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.11 mrg movel d1,d1 | 1387 1.11 mrg bne Ladddf$ret | 1388 1.1 mrg bclr IMM (31),d7 | 1389 1.1 mrg bra Ladddf$ret | 1390 1.1 mrg 2: 1391 1.1 mrg andl IMM (0x000fffff),d0 | check for NaN (nonzero fraction) 1392 1.1 mrg orl d1,d0 | 1393 1.1 mrg bne Ld$inop | 1394 1.1 mrg bra Ld$infty | 1395 1.1 mrg 1396 1.1 mrg Ladddf$ret$1: 1397 1.1 mrg #ifndef __mcoldfire__ 1398 1.1 mrg moveml sp@+,a2-a3 | restore regs and exit 1399 1.1 mrg #else 1400 1.1 mrg movel sp@+,a4 1401 1.1 mrg movel sp@+,a3 1402 1.1 mrg movel sp@+,a2 1403 1.1 mrg #endif 1404 1.1 mrg 1405 1.1 mrg Ladddf$ret: 1406 1.1 mrg | Normal exit. 1407 1.1 mrg PICLEA SYM (_fpCCR),a0 1408 1.1 mrg movew IMM (0),a0@ 1409 1.1 mrg orl d7,d0 | put sign bit back 1410 1.1 mrg #ifndef __mcoldfire__ 1411 1.1 mrg moveml sp@+,d2-d7 1412 1.1 mrg #else 1413 1.1 mrg moveml sp@,d2-d7 1414 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 1415 1.1 mrg | be adjusted here. 1416 1.1 mrg #endif 1417 1.1 mrg unlk a6 1418 1.1 mrg rts 1419 1.1 mrg 1420 1.1 mrg Ladddf$ret$den: 1421 1.1 mrg | Return a denormalized number. 1422 1.1 mrg #ifndef __mcoldfire__ 1423 1.1 mrg lsrl IMM (1),d0 | shift right once more 1424 1.1 mrg roxrl IMM (1),d1 | 1425 1.1 mrg #else 1426 1.1 mrg lsrl IMM (1),d1 1427 1.1 mrg btst IMM (0),d0 1428 1.1 mrg beq 10f 1429 1.1 mrg bset IMM (31),d1 1430 1.1 mrg 10: lsrl IMM (1),d0 1431 1.1 mrg #endif 1432 1.1 mrg bra Ladddf$ret 1433 1.1 mrg 1434 1.1 mrg Ladddf$nf: 1435 1.1 mrg moveq IMM (ADD),d5 1436 1.1 mrg | This could be faster but it is not worth the effort, since it is not 1437 1.1 mrg | executed very often. We sacrifice speed for clarity here. 1438 1.1 mrg movel a6@(8),d0 | get the numbers back (remember that we 1439 1.1 mrg movel a6@(12),d1 | did some processing already) 1440 1.1 mrg movel a6@(16),d2 | 1441 1.1 mrg movel a6@(20),d3 | 1442 1.1 mrg movel IMM (0x7ff00000),d4 | useful constant (INFINITY) 1443 1.1 mrg movel d0,d7 | save sign bits 1444 1.1 mrg movel d2,d6 | 1445 1.1 mrg bclr IMM (31),d0 | clear sign bits 1446 1.1 mrg bclr IMM (31),d2 | 1447 1.1 mrg | We know that one of them is either NaN of +/-INFINITY 1448 1.1 mrg | Check for NaN (if either one is NaN return NaN) 1449 1.1 mrg cmpl d4,d0 | check first a (d0) 1450 1.1 mrg bhi Ld$inop | if d0 > 0x7ff00000 or equal and 1451 1.1 mrg bne 2f 1452 1.1 mrg tstl d1 | d1 > 0, a is NaN 1453 1.1 mrg bne Ld$inop | 1454 1.1 mrg 2: cmpl d4,d2 | check now b (d1) 1455 1.1 mrg bhi Ld$inop | 1456 1.1 mrg bne 3f 1457 1.1 mrg tstl d3 | 1458 1.1 mrg bne Ld$inop | 1459 1.1 mrg 3: 1460 1.1 mrg | Now comes the check for +/-INFINITY. We know that both are (maybe not 1461 1.1 mrg | finite) numbers, but we have to check if both are infinite whether we 1462 1.1 mrg | are adding or subtracting them. 1463 1.1 mrg eorl d7,d6 | to check sign bits 1464 1.1 mrg bmi 1f 1465 1.1 mrg andl IMM (0x80000000),d7 | get (common) sign bit 1466 1.1 mrg bra Ld$infty 1467 1.1 mrg 1: 1468 1.1 mrg | We know one (or both) are infinite, so we test for equality between the 1469 1.1 mrg | two numbers (if they are equal they have to be infinite both, so we 1470 1.1 mrg | return NaN). 1471 1.1 mrg cmpl d2,d0 | are both infinite? 1472 1.1 mrg bne 1f | if d0 <> d2 they are not equal 1473 1.1 mrg cmpl d3,d1 | if d0 == d2 test d3 and d1 1474 1.1 mrg beq Ld$inop | if equal return NaN 1475 1.1 mrg 1: 1476 1.1 mrg andl IMM (0x80000000),d7 | get a's sign bit ' 1477 1.1 mrg cmpl d4,d0 | test now for infinity 1478 1.1 mrg beq Ld$infty | if a is INFINITY return with this sign 1479 1.1 mrg bchg IMM (31),d7 | else we know b is INFINITY and has 1480 1.1 mrg bra Ld$infty | the opposite sign 1481 1.1 mrg 1482 1.1 mrg |============================================================================= 1483 1.1 mrg | __muldf3 1484 1.1 mrg |============================================================================= 1485 1.1 mrg 1486 1.1 mrg | double __muldf3(double, double); 1487 1.1 mrg FUNC(__muldf3) 1488 1.1 mrg SYM (__muldf3): 1489 1.1 mrg #ifndef __mcoldfire__ 1490 1.1 mrg link a6,IMM (0) 1491 1.1 mrg moveml d2-d7,sp@- 1492 1.1 mrg #else 1493 1.1 mrg link a6,IMM (-24) 1494 1.1 mrg moveml d2-d7,sp@ 1495 1.1 mrg #endif 1496 1.1 mrg movel a6@(8),d0 | get a into d0-d1 1497 1.1 mrg movel a6@(12),d1 | 1498 1.1 mrg movel a6@(16),d2 | and b into d2-d3 1499 1.1 mrg movel a6@(20),d3 | 1500 1.1 mrg movel d0,d7 | d7 will hold the sign of the product 1501 1.1 mrg eorl d2,d7 | 1502 1.1 mrg andl IMM (0x80000000),d7 | 1503 1.1 mrg movel d7,a0 | save sign bit into a0 1504 1.1 mrg movel IMM (0x7ff00000),d7 | useful constant (+INFINITY) 1505 1.1 mrg movel d7,d6 | another (mask for fraction) 1506 1.1 mrg notl d6 | 1507 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 1508 1.1 mrg movel d0,d4 | 1509 1.1 mrg orl d1,d4 | 1510 1.1 mrg beq Lmuldf$a$0 | branch if a is zero 1511 1.1 mrg movel d0,d4 | 1512 1.1 mrg bclr IMM (31),d2 | get rid of b's sign bit ' 1513 1.1 mrg movel d2,d5 | 1514 1.1 mrg orl d3,d5 | 1515 1.1 mrg beq Lmuldf$b$0 | branch if b is zero 1516 1.1 mrg movel d2,d5 | 1517 1.1 mrg cmpl d7,d0 | is a big? 1518 1.1 mrg bhi Lmuldf$inop | if a is NaN return NaN 1519 1.1 mrg beq Lmuldf$a$nf | we still have to check d1 and b ... 1520 1.1 mrg cmpl d7,d2 | now compare b with INFINITY 1521 1.1 mrg bhi Lmuldf$inop | is b NaN? 1522 1.1 mrg beq Lmuldf$b$nf | we still have to check d3 ... 1523 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 1524 1.1 mrg | Now we get the exponents into d4 and d5. 1525 1.1 mrg andl d7,d4 | isolate exponent in d4 1526 1.1 mrg beq Lmuldf$a$den | if exponent zero, have denormalized 1527 1.1 mrg andl d6,d0 | isolate fraction 1528 1.1 mrg orl IMM (0x00100000),d0 | and put hidden bit back 1529 1.1 mrg swap d4 | I like exponents in the first byte 1530 1.1 mrg #ifndef __mcoldfire__ 1531 1.1 mrg lsrw IMM (4),d4 | 1532 1.1 mrg #else 1533 1.1 mrg lsrl IMM (4),d4 | 1534 1.1 mrg #endif 1535 1.1 mrg Lmuldf$1: 1536 1.1 mrg andl d7,d5 | 1537 1.1 mrg beq Lmuldf$b$den | 1538 1.1 mrg andl d6,d2 | 1539 1.1 mrg orl IMM (0x00100000),d2 | and put hidden bit back 1540 1.1 mrg swap d5 | 1541 1.1 mrg #ifndef __mcoldfire__ 1542 1.1 mrg lsrw IMM (4),d5 | 1543 1.1 mrg #else 1544 1.1 mrg lsrl IMM (4),d5 | 1545 1.1 mrg #endif 1546 1.1 mrg Lmuldf$2: | 1547 1.1 mrg #ifndef __mcoldfire__ 1548 1.1 mrg addw d5,d4 | add exponents 1549 1.1 mrg subw IMM (D_BIAS+1),d4 | and subtract bias (plus one) 1550 1.1 mrg #else 1551 1.1 mrg addl d5,d4 | add exponents 1552 1.1 mrg subl IMM (D_BIAS+1),d4 | and subtract bias (plus one) 1553 1.1 mrg #endif 1554 1.1 mrg 1555 1.1 mrg | We are now ready to do the multiplication. The situation is as follows: 1556 1.1 mrg | both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were 1557 1.1 mrg | denormalized to start with!), which means that in the product bit 104 1558 1.1 mrg | (which will correspond to bit 8 of the fourth long) is set. 1559 1.1 mrg 1560 1.1 mrg | Here we have to do the product. 1561 1.1 mrg | To do it we have to juggle the registers back and forth, as there are not 1562 1.1 mrg | enough to keep everything in them. So we use the address registers to keep 1563 1.1 mrg | some intermediate data. 1564 1.1 mrg 1565 1.1 mrg #ifndef __mcoldfire__ 1566 1.1 mrg moveml a2-a3,sp@- | save a2 and a3 for temporary use 1567 1.1 mrg #else 1568 1.1 mrg movel a2,sp@- 1569 1.1 mrg movel a3,sp@- 1570 1.1 mrg movel a4,sp@- 1571 1.1 mrg #endif 1572 1.1 mrg movel IMM (0),a2 | a2 is a null register 1573 1.1 mrg movel d4,a3 | and a3 will preserve the exponent 1574 1.1 mrg 1575 1.1 mrg | First, shift d2-d3 so bit 20 becomes bit 31: 1576 1.1 mrg #ifndef __mcoldfire__ 1577 1.1 mrg rorl IMM (5),d2 | rotate d2 5 places right 1578 1.1 mrg swap d2 | and swap it 1579 1.1 mrg rorl IMM (5),d3 | do the same thing with d3 1580 1.1 mrg swap d3 | 1581 1.1 mrg movew d3,d6 | get the rightmost 11 bits of d3 1582 1.1 mrg andw IMM (0x07ff),d6 | 1583 1.1 mrg orw d6,d2 | and put them into d2 1584 1.1 mrg andw IMM (0xf800),d3 | clear those bits in d3 1585 1.1 mrg #else 1586 1.1 mrg moveq IMM (11),d7 | left shift d2 11 bits 1587 1.1 mrg lsll d7,d2 1588 1.1 mrg movel d3,d6 | get a copy of d3 1589 1.1 mrg lsll d7,d3 | left shift d3 11 bits 1590 1.1 mrg andl IMM (0xffe00000),d6 | get the top 11 bits of d3 1591 1.1 mrg moveq IMM (21),d7 | right shift them 21 bits 1592 1.1 mrg lsrl d7,d6 1593 1.1 mrg orl d6,d2 | stick them at the end of d2 1594 1.1 mrg #endif 1595 1.1 mrg 1596 1.1 mrg movel d2,d6 | move b into d6-d7 1597 1.1 mrg movel d3,d7 | move a into d4-d5 1598 1.1 mrg movel d0,d4 | and clear d0-d1-d2-d3 (to put result) 1599 1.1 mrg movel d1,d5 | 1600 1.1 mrg movel IMM (0),d3 | 1601 1.1 mrg movel d3,d2 | 1602 1.1 mrg movel d3,d1 | 1603 1.1 mrg movel d3,d0 | 1604 1.1 mrg 1605 1.1 mrg | We use a1 as counter: 1606 1.1 mrg movel IMM (DBL_MANT_DIG-1),a1 1607 1.1 mrg #ifndef __mcoldfire__ 1608 1.1 mrg exg d7,a1 1609 1.1 mrg #else 1610 1.1 mrg movel d7,a4 1611 1.1 mrg movel a1,d7 1612 1.1 mrg movel a4,a1 1613 1.1 mrg #endif 1614 1.1 mrg 1615 1.1 mrg 1: 1616 1.1 mrg #ifndef __mcoldfire__ 1617 1.1 mrg exg d7,a1 | put counter back in a1 1618 1.1 mrg #else 1619 1.1 mrg movel d7,a4 1620 1.1 mrg movel a1,d7 1621 1.1 mrg movel a4,a1 1622 1.1 mrg #endif 1623 1.1 mrg addl d3,d3 | shift sum once left 1624 1.1 mrg addxl d2,d2 | 1625 1.1 mrg addxl d1,d1 | 1626 1.1 mrg addxl d0,d0 | 1627 1.1 mrg addl d7,d7 | 1628 1.1 mrg addxl d6,d6 | 1629 1.1 mrg bcc 2f | if bit clear skip the following 1630 1.1 mrg #ifndef __mcoldfire__ 1631 1.1 mrg exg d7,a2 | 1632 1.1 mrg #else 1633 1.1 mrg movel d7,a4 1634 1.1 mrg movel a2,d7 1635 1.1 mrg movel a4,a2 1636 1.1 mrg #endif 1637 1.1 mrg addl d5,d3 | else add a to the sum 1638 1.1 mrg addxl d4,d2 | 1639 1.1 mrg addxl d7,d1 | 1640 1.1 mrg addxl d7,d0 | 1641 1.1 mrg #ifndef __mcoldfire__ 1642 1.1 mrg exg d7,a2 | 1643 1.1 mrg #else 1644 1.1 mrg movel d7,a4 1645 1.1 mrg movel a2,d7 1646 1.1 mrg movel a4,a2 1647 1.1 mrg #endif 1648 1.1 mrg 2: 1649 1.1 mrg #ifndef __mcoldfire__ 1650 1.1 mrg exg d7,a1 | put counter in d7 1651 1.1 mrg dbf d7,1b | decrement and branch 1652 1.1 mrg #else 1653 1.1 mrg movel d7,a4 1654 1.1 mrg movel a1,d7 1655 1.1 mrg movel a4,a1 1656 1.1 mrg subql IMM (1),d7 1657 1.1 mrg bpl 1b 1658 1.1 mrg #endif 1659 1.1 mrg 1660 1.1 mrg movel a3,d4 | restore exponent 1661 1.1 mrg #ifndef __mcoldfire__ 1662 1.1 mrg moveml sp@+,a2-a3 1663 1.1 mrg #else 1664 1.1 mrg movel sp@+,a4 1665 1.1 mrg movel sp@+,a3 1666 1.1 mrg movel sp@+,a2 1667 1.1 mrg #endif 1668 1.1 mrg 1669 1.1 mrg | Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The 1670 1.1 mrg | first thing to do now is to normalize it so bit 8 becomes bit 1671 1.1 mrg | DBL_MANT_DIG-32 (to do the rounding); later we will shift right. 1672 1.1 mrg swap d0 1673 1.1 mrg swap d1 1674 1.1 mrg movew d1,d0 1675 1.1 mrg swap d2 1676 1.1 mrg movew d2,d1 1677 1.1 mrg swap d3 1678 1.1 mrg movew d3,d2 1679 1.1 mrg movew IMM (0),d3 1680 1.1 mrg #ifndef __mcoldfire__ 1681 1.1 mrg lsrl IMM (1),d0 1682 1.1 mrg roxrl IMM (1),d1 1683 1.1 mrg roxrl IMM (1),d2 1684 1.1 mrg roxrl IMM (1),d3 1685 1.1 mrg lsrl IMM (1),d0 1686 1.1 mrg roxrl IMM (1),d1 1687 1.1 mrg roxrl IMM (1),d2 1688 1.1 mrg roxrl IMM (1),d3 1689 1.1 mrg lsrl IMM (1),d0 1690 1.1 mrg roxrl IMM (1),d1 1691 1.1 mrg roxrl IMM (1),d2 1692 1.1 mrg roxrl IMM (1),d3 1693 1.1 mrg #else 1694 1.1 mrg moveq IMM (29),d6 1695 1.1 mrg lsrl IMM (3),d3 1696 1.1 mrg movel d2,d7 1697 1.1 mrg lsll d6,d7 1698 1.1 mrg orl d7,d3 1699 1.1 mrg lsrl IMM (3),d2 1700 1.1 mrg movel d1,d7 1701 1.1 mrg lsll d6,d7 1702 1.1 mrg orl d7,d2 1703 1.1 mrg lsrl IMM (3),d1 1704 1.1 mrg movel d0,d7 1705 1.1 mrg lsll d6,d7 1706 1.1 mrg orl d7,d1 1707 1.1 mrg lsrl IMM (3),d0 1708 1.1 mrg #endif 1709 1.1 mrg 1710 1.1 mrg | Now round, check for over- and underflow, and exit. 1711 1.1 mrg movel a0,d7 | get sign bit back into d7 1712 1.1 mrg moveq IMM (MULTIPLY),d5 1713 1.1 mrg 1714 1.1 mrg btst IMM (DBL_MANT_DIG+1-32),d0 1715 1.1 mrg beq Lround$exit 1716 1.1 mrg #ifndef __mcoldfire__ 1717 1.1 mrg lsrl IMM (1),d0 1718 1.1 mrg roxrl IMM (1),d1 1719 1.1 mrg addw IMM (1),d4 1720 1.1 mrg #else 1721 1.1 mrg lsrl IMM (1),d1 1722 1.1 mrg btst IMM (0),d0 1723 1.1 mrg beq 10f 1724 1.1 mrg bset IMM (31),d1 1725 1.1 mrg 10: lsrl IMM (1),d0 1726 1.1 mrg addl IMM (1),d4 1727 1.1 mrg #endif 1728 1.1 mrg bra Lround$exit 1729 1.1 mrg 1730 1.1 mrg Lmuldf$inop: 1731 1.1 mrg moveq IMM (MULTIPLY),d5 1732 1.1 mrg bra Ld$inop 1733 1.1 mrg 1734 1.1 mrg Lmuldf$b$nf: 1735 1.1 mrg moveq IMM (MULTIPLY),d5 1736 1.1 mrg movel a0,d7 | get sign bit back into d7 1737 1.1 mrg tstl d3 | we know d2 == 0x7ff00000, so check d3 1738 1.1 mrg bne Ld$inop | if d3 <> 0 b is NaN 1739 1.1 mrg bra Ld$overflow | else we have overflow (since a is finite) 1740 1.1 mrg 1741 1.1 mrg Lmuldf$a$nf: 1742 1.1 mrg moveq IMM (MULTIPLY),d5 1743 1.1 mrg movel a0,d7 | get sign bit back into d7 1744 1.1 mrg tstl d1 | we know d0 == 0x7ff00000, so check d1 1745 1.1 mrg bne Ld$inop | if d1 <> 0 a is NaN 1746 1.1 mrg bra Ld$overflow | else signal overflow 1747 1.1 mrg 1748 1.1 mrg | If either number is zero return zero, unless the other is +/-INFINITY or 1749 1.1 mrg | NaN, in which case we return NaN. 1750 1.1 mrg Lmuldf$b$0: 1751 1.1 mrg moveq IMM (MULTIPLY),d5 1752 1.1 mrg #ifndef __mcoldfire__ 1753 1.1 mrg exg d2,d0 | put b (==0) into d0-d1 1754 1.1 mrg exg d3,d1 | and a (with sign bit cleared) into d2-d3 1755 1.1 mrg movel a0,d0 | set result sign 1756 1.1 mrg #else 1757 1.1 mrg movel d0,d2 | put a into d2-d3 1758 1.1 mrg movel d1,d3 1759 1.1 mrg movel a0,d0 | put result zero into d0-d1 1760 1.1 mrg movq IMM(0),d1 1761 1.1 mrg #endif 1762 1.1 mrg bra 1f 1763 1.1 mrg Lmuldf$a$0: 1764 1.1 mrg movel a0,d0 | set result sign 1765 1.1 mrg movel a6@(16),d2 | put b into d2-d3 again 1766 1.1 mrg movel a6@(20),d3 | 1767 1.1 mrg bclr IMM (31),d2 | clear sign bit 1768 1.1 mrg 1: cmpl IMM (0x7ff00000),d2 | check for non-finiteness 1769 1.1 mrg bge Ld$inop | in case NaN or +/-INFINITY return NaN 1770 1.1 mrg PICLEA SYM (_fpCCR),a0 1771 1.1 mrg movew IMM (0),a0@ 1772 1.1 mrg #ifndef __mcoldfire__ 1773 1.1 mrg moveml sp@+,d2-d7 1774 1.1 mrg #else 1775 1.1 mrg moveml sp@,d2-d7 1776 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 1777 1.1 mrg | be adjusted here. 1778 1.1 mrg #endif 1779 1.1 mrg unlk a6 1780 1.1 mrg rts 1781 1.1 mrg 1782 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 1783 1.1 mrg | hidden bit back into the fraction; instead we shift left until bit 21 1784 1.1 mrg | (the hidden bit) is set, adjusting the exponent accordingly. We do this 1785 1.1 mrg | to ensure that the product of the fractions is close to 1. 1786 1.1 mrg Lmuldf$a$den: 1787 1.1 mrg movel IMM (1),d4 1788 1.1 mrg andl d6,d0 1789 1.1 mrg 1: addl d1,d1 | shift a left until bit 20 is set 1790 1.1 mrg addxl d0,d0 | 1791 1.1 mrg #ifndef __mcoldfire__ 1792 1.1 mrg subw IMM (1),d4 | and adjust exponent 1793 1.1 mrg #else 1794 1.1 mrg subl IMM (1),d4 | and adjust exponent 1795 1.1 mrg #endif 1796 1.1 mrg btst IMM (20),d0 | 1797 1.1 mrg bne Lmuldf$1 | 1798 1.1 mrg bra 1b 1799 1.1 mrg 1800 1.1 mrg Lmuldf$b$den: 1801 1.1 mrg movel IMM (1),d5 1802 1.1 mrg andl d6,d2 1803 1.1 mrg 1: addl d3,d3 | shift b left until bit 20 is set 1804 1.1 mrg addxl d2,d2 | 1805 1.1 mrg #ifndef __mcoldfire__ 1806 1.1 mrg subw IMM (1),d5 | and adjust exponent 1807 1.1 mrg #else 1808 1.1 mrg subql IMM (1),d5 | and adjust exponent 1809 1.1 mrg #endif 1810 1.1 mrg btst IMM (20),d2 | 1811 1.1 mrg bne Lmuldf$2 | 1812 1.1 mrg bra 1b 1813 1.1 mrg 1814 1.1 mrg 1815 1.1 mrg |============================================================================= 1816 1.1 mrg | __divdf3 1817 1.1 mrg |============================================================================= 1818 1.1 mrg 1819 1.1 mrg | double __divdf3(double, double); 1820 1.1 mrg FUNC(__divdf3) 1821 1.1 mrg SYM (__divdf3): 1822 1.1 mrg #ifndef __mcoldfire__ 1823 1.1 mrg link a6,IMM (0) 1824 1.1 mrg moveml d2-d7,sp@- 1825 1.1 mrg #else 1826 1.1 mrg link a6,IMM (-24) 1827 1.1 mrg moveml d2-d7,sp@ 1828 1.1 mrg #endif 1829 1.1 mrg movel a6@(8),d0 | get a into d0-d1 1830 1.1 mrg movel a6@(12),d1 | 1831 1.1 mrg movel a6@(16),d2 | and b into d2-d3 1832 1.1 mrg movel a6@(20),d3 | 1833 1.1 mrg movel d0,d7 | d7 will hold the sign of the result 1834 1.1 mrg eorl d2,d7 | 1835 1.1 mrg andl IMM (0x80000000),d7 1836 1.1 mrg movel d7,a0 | save sign into a0 1837 1.1 mrg movel IMM (0x7ff00000),d7 | useful constant (+INFINITY) 1838 1.1 mrg movel d7,d6 | another (mask for fraction) 1839 1.1 mrg notl d6 | 1840 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 1841 1.1 mrg movel d0,d4 | 1842 1.1 mrg orl d1,d4 | 1843 1.1 mrg beq Ldivdf$a$0 | branch if a is zero 1844 1.1 mrg movel d0,d4 | 1845 1.1 mrg bclr IMM (31),d2 | get rid of b's sign bit ' 1846 1.1 mrg movel d2,d5 | 1847 1.1 mrg orl d3,d5 | 1848 1.1 mrg beq Ldivdf$b$0 | branch if b is zero 1849 1.1 mrg movel d2,d5 1850 1.1 mrg cmpl d7,d0 | is a big? 1851 1.1 mrg bhi Ldivdf$inop | if a is NaN return NaN 1852 1.1 mrg beq Ldivdf$a$nf | if d0 == 0x7ff00000 we check d1 1853 1.1 mrg cmpl d7,d2 | now compare b with INFINITY 1854 1.1 mrg bhi Ldivdf$inop | if b is NaN return NaN 1855 1.1 mrg beq Ldivdf$b$nf | if d2 == 0x7ff00000 we check d3 1856 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 1857 1.1 mrg | Now we get the exponents into d4 and d5 and normalize the numbers to 1858 1.1 mrg | ensure that the ratio of the fractions is around 1. We do this by 1859 1.1 mrg | making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit) 1860 1.1 mrg | set, even if they were denormalized to start with. 1861 1.1 mrg | Thus, the result will satisfy: 2 > result > 1/2. 1862 1.1 mrg andl d7,d4 | and isolate exponent in d4 1863 1.1 mrg beq Ldivdf$a$den | if exponent is zero we have a denormalized 1864 1.1 mrg andl d6,d0 | and isolate fraction 1865 1.1 mrg orl IMM (0x00100000),d0 | and put hidden bit back 1866 1.1 mrg swap d4 | I like exponents in the first byte 1867 1.1 mrg #ifndef __mcoldfire__ 1868 1.1 mrg lsrw IMM (4),d4 | 1869 1.1 mrg #else 1870 1.1 mrg lsrl IMM (4),d4 | 1871 1.1 mrg #endif 1872 1.1 mrg Ldivdf$1: | 1873 1.1 mrg andl d7,d5 | 1874 1.1 mrg beq Ldivdf$b$den | 1875 1.1 mrg andl d6,d2 | 1876 1.1 mrg orl IMM (0x00100000),d2 1877 1.1 mrg swap d5 | 1878 1.1 mrg #ifndef __mcoldfire__ 1879 1.1 mrg lsrw IMM (4),d5 | 1880 1.1 mrg #else 1881 1.1 mrg lsrl IMM (4),d5 | 1882 1.1 mrg #endif 1883 1.1 mrg Ldivdf$2: | 1884 1.1 mrg #ifndef __mcoldfire__ 1885 1.1 mrg subw d5,d4 | subtract exponents 1886 1.1 mrg addw IMM (D_BIAS),d4 | and add bias 1887 1.1 mrg #else 1888 1.1 mrg subl d5,d4 | subtract exponents 1889 1.1 mrg addl IMM (D_BIAS),d4 | and add bias 1890 1.1 mrg #endif 1891 1.1 mrg 1892 1.1 mrg | We are now ready to do the division. We have prepared things in such a way 1893 1.1 mrg | that the ratio of the fractions will be less than 2 but greater than 1/2. 1894 1.1 mrg | At this point the registers in use are: 1895 1.1 mrg | d0-d1 hold a (first operand, bit DBL_MANT_DIG-32=0, bit 1896 1.1 mrg | DBL_MANT_DIG-1-32=1) 1897 1.1 mrg | d2-d3 hold b (second operand, bit DBL_MANT_DIG-32=1) 1898 1.1 mrg | d4 holds the difference of the exponents, corrected by the bias 1899 1.1 mrg | a0 holds the sign of the ratio 1900 1.1 mrg 1901 1.1 mrg | To do the rounding correctly we need to keep information about the 1902 1.1 mrg | nonsignificant bits. One way to do this would be to do the division 1903 1.1 mrg | using four registers; another is to use two registers (as originally 1904 1.1 mrg | I did), but use a sticky bit to preserve information about the 1905 1.1 mrg | fractional part. Note that we can keep that info in a1, which is not 1906 1.1 mrg | used. 1907 1.1 mrg movel IMM (0),d6 | d6-d7 will hold the result 1908 1.1 mrg movel d6,d7 | 1909 1.1 mrg movel IMM (0),a1 | and a1 will hold the sticky bit 1910 1.1 mrg 1911 1.1 mrg movel IMM (DBL_MANT_DIG-32+1),d5 1912 1.1 mrg 1913 1.1 mrg 1: cmpl d0,d2 | is a < b? 1914 1.1 mrg bhi 3f | if b > a skip the following 1915 1.1 mrg beq 4f | if d0==d2 check d1 and d3 1916 1.1 mrg 2: subl d3,d1 | 1917 1.1 mrg subxl d2,d0 | a <-- a - b 1918 1.1 mrg bset d5,d6 | set the corresponding bit in d6 1919 1.1 mrg 3: addl d1,d1 | shift a by 1 1920 1.1 mrg addxl d0,d0 | 1921 1.1 mrg #ifndef __mcoldfire__ 1922 1.1 mrg dbra d5,1b | and branch back 1923 1.1 mrg #else 1924 1.1 mrg subql IMM (1), d5 1925 1.1 mrg bpl 1b 1926 1.1 mrg #endif 1927 1.1 mrg bra 5f 1928 1.1 mrg 4: cmpl d1,d3 | here d0==d2, so check d1 and d3 1929 1.1 mrg bhi 3b | if d1 > d2 skip the subtraction 1930 1.1 mrg bra 2b | else go do it 1931 1.1 mrg 5: 1932 1.1 mrg | Here we have to start setting the bits in the second long. 1933 1.1 mrg movel IMM (31),d5 | again d5 is counter 1934 1.1 mrg 1935 1.1 mrg 1: cmpl d0,d2 | is a < b? 1936 1.1 mrg bhi 3f | if b > a skip the following 1937 1.1 mrg beq 4f | if d0==d2 check d1 and d3 1938 1.1 mrg 2: subl d3,d1 | 1939 1.1 mrg subxl d2,d0 | a <-- a - b 1940 1.1 mrg bset d5,d7 | set the corresponding bit in d7 1941 1.1 mrg 3: addl d1,d1 | shift a by 1 1942 1.1 mrg addxl d0,d0 | 1943 1.1 mrg #ifndef __mcoldfire__ 1944 1.1 mrg dbra d5,1b | and branch back 1945 1.1 mrg #else 1946 1.1 mrg subql IMM (1), d5 1947 1.1 mrg bpl 1b 1948 1.1 mrg #endif 1949 1.1 mrg bra 5f 1950 1.1 mrg 4: cmpl d1,d3 | here d0==d2, so check d1 and d3 1951 1.1 mrg bhi 3b | if d1 > d2 skip the subtraction 1952 1.1 mrg bra 2b | else go do it 1953 1.1 mrg 5: 1954 1.1 mrg | Now go ahead checking until we hit a one, which we store in d2. 1955 1.1 mrg movel IMM (DBL_MANT_DIG),d5 1956 1.1 mrg 1: cmpl d2,d0 | is a < b? 1957 1.1 mrg bhi 4f | if b < a, exit 1958 1.1 mrg beq 3f | if d0==d2 check d1 and d3 1959 1.1 mrg 2: addl d1,d1 | shift a by 1 1960 1.1 mrg addxl d0,d0 | 1961 1.1 mrg #ifndef __mcoldfire__ 1962 1.1 mrg dbra d5,1b | and branch back 1963 1.1 mrg #else 1964 1.1 mrg subql IMM (1), d5 1965 1.1 mrg bpl 1b 1966 1.1 mrg #endif 1967 1.1 mrg movel IMM (0),d2 | here no sticky bit was found 1968 1.1 mrg movel d2,d3 1969 1.1 mrg bra 5f 1970 1.1 mrg 3: cmpl d1,d3 | here d0==d2, so check d1 and d3 1971 1.1 mrg bhi 2b | if d1 > d2 go back 1972 1.1 mrg 4: 1973 1.1 mrg | Here put the sticky bit in d2-d3 (in the position which actually corresponds 1974 1.1 mrg | to it; if you don't do this the algorithm loses in some cases). ' 1975 1.1 mrg movel IMM (0),d2 1976 1.1 mrg movel d2,d3 1977 1.1 mrg #ifndef __mcoldfire__ 1978 1.1 mrg subw IMM (DBL_MANT_DIG),d5 1979 1.1 mrg addw IMM (63),d5 1980 1.1 mrg cmpw IMM (31),d5 1981 1.1 mrg #else 1982 1.1 mrg subl IMM (DBL_MANT_DIG),d5 1983 1.1 mrg addl IMM (63),d5 1984 1.1 mrg cmpl IMM (31),d5 1985 1.1 mrg #endif 1986 1.1 mrg bhi 2f 1987 1.1 mrg 1: bset d5,d3 1988 1.1 mrg bra 5f 1989 1.1 mrg #ifndef __mcoldfire__ 1990 1.1 mrg subw IMM (32),d5 1991 1.1 mrg #else 1992 1.1 mrg subl IMM (32),d5 1993 1.1 mrg #endif 1994 1.1 mrg 2: bset d5,d2 1995 1.1 mrg 5: 1996 1.1 mrg | Finally we are finished! Move the longs in the address registers to 1997 1.1 mrg | their final destination: 1998 1.1 mrg movel d6,d0 1999 1.1 mrg movel d7,d1 2000 1.1 mrg movel IMM (0),d3 2001 1.1 mrg 2002 1.1 mrg | Here we have finished the division, with the result in d0-d1-d2-d3, with 2003 1.1 mrg | 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set. 2004 1.1 mrg | If it is not, then definitely bit 21 is set. Normalize so bit 22 is 2005 1.1 mrg | not set: 2006 1.1 mrg btst IMM (DBL_MANT_DIG-32+1),d0 2007 1.1 mrg beq 1f 2008 1.1 mrg #ifndef __mcoldfire__ 2009 1.1 mrg lsrl IMM (1),d0 2010 1.1 mrg roxrl IMM (1),d1 2011 1.1 mrg roxrl IMM (1),d2 2012 1.1 mrg roxrl IMM (1),d3 2013 1.1 mrg addw IMM (1),d4 2014 1.1 mrg #else 2015 1.1 mrg lsrl IMM (1),d3 2016 1.1 mrg btst IMM (0),d2 2017 1.1 mrg beq 10f 2018 1.1 mrg bset IMM (31),d3 2019 1.1 mrg 10: lsrl IMM (1),d2 2020 1.1 mrg btst IMM (0),d1 2021 1.1 mrg beq 11f 2022 1.1 mrg bset IMM (31),d2 2023 1.1 mrg 11: lsrl IMM (1),d1 2024 1.1 mrg btst IMM (0),d0 2025 1.1 mrg beq 12f 2026 1.1 mrg bset IMM (31),d1 2027 1.1 mrg 12: lsrl IMM (1),d0 2028 1.1 mrg addl IMM (1),d4 2029 1.1 mrg #endif 2030 1.1 mrg 1: 2031 1.1 mrg | Now round, check for over- and underflow, and exit. 2032 1.1 mrg movel a0,d7 | restore sign bit to d7 2033 1.1 mrg moveq IMM (DIVIDE),d5 2034 1.1 mrg bra Lround$exit 2035 1.1 mrg 2036 1.1 mrg Ldivdf$inop: 2037 1.1 mrg moveq IMM (DIVIDE),d5 2038 1.1 mrg bra Ld$inop 2039 1.1 mrg 2040 1.1 mrg Ldivdf$a$0: 2041 1.1 mrg | If a is zero check to see whether b is zero also. In that case return 2042 1.1 mrg | NaN; then check if b is NaN, and return NaN also in that case. Else 2043 1.1 mrg | return a properly signed zero. 2044 1.1 mrg moveq IMM (DIVIDE),d5 2045 1.1 mrg bclr IMM (31),d2 | 2046 1.1 mrg movel d2,d4 | 2047 1.1 mrg orl d3,d4 | 2048 1.1 mrg beq Ld$inop | if b is also zero return NaN 2049 1.1 mrg cmpl IMM (0x7ff00000),d2 | check for NaN 2050 1.1 mrg bhi Ld$inop | 2051 1.1 mrg blt 1f | 2052 1.1 mrg tstl d3 | 2053 1.1 mrg bne Ld$inop | 2054 1.1 mrg 1: movel a0,d0 | else return signed zero 2055 1.1 mrg moveq IMM(0),d1 | 2056 1.1 mrg PICLEA SYM (_fpCCR),a0 | clear exception flags 2057 1.1 mrg movew IMM (0),a0@ | 2058 1.1 mrg #ifndef __mcoldfire__ 2059 1.1 mrg moveml sp@+,d2-d7 | 2060 1.1 mrg #else 2061 1.1 mrg moveml sp@,d2-d7 | 2062 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2063 1.1 mrg | be adjusted here. 2064 1.1 mrg #endif 2065 1.1 mrg unlk a6 | 2066 1.1 mrg rts | 2067 1.1 mrg 2068 1.1 mrg Ldivdf$b$0: 2069 1.1 mrg moveq IMM (DIVIDE),d5 2070 1.1 mrg | If we got here a is not zero. Check if a is NaN; in that case return NaN, 2071 1.1 mrg | else return +/-INFINITY. Remember that a is in d0 with the sign bit 2072 1.1 mrg | cleared already. 2073 1.1 mrg movel a0,d7 | put a's sign bit back in d7 ' 2074 1.1 mrg cmpl IMM (0x7ff00000),d0 | compare d0 with INFINITY 2075 1.1 mrg bhi Ld$inop | if larger it is NaN 2076 1.1 mrg tstl d1 | 2077 1.1 mrg bne Ld$inop | 2078 1.1 mrg bra Ld$div$0 | else signal DIVIDE_BY_ZERO 2079 1.1 mrg 2080 1.1 mrg Ldivdf$b$nf: 2081 1.1 mrg moveq IMM (DIVIDE),d5 2082 1.1 mrg | If d2 == 0x7ff00000 we have to check d3. 2083 1.1 mrg tstl d3 | 2084 1.1 mrg bne Ld$inop | if d3 <> 0, b is NaN 2085 1.1 mrg bra Ld$underflow | else b is +/-INFINITY, so signal underflow 2086 1.1 mrg 2087 1.1 mrg Ldivdf$a$nf: 2088 1.1 mrg moveq IMM (DIVIDE),d5 2089 1.1 mrg | If d0 == 0x7ff00000 we have to check d1. 2090 1.1 mrg tstl d1 | 2091 1.1 mrg bne Ld$inop | if d1 <> 0, a is NaN 2092 1.1 mrg | If a is INFINITY we have to check b 2093 1.1 mrg cmpl d7,d2 | compare b with INFINITY 2094 1.1 mrg bge Ld$inop | if b is NaN or INFINITY return NaN 2095 1.11 mrg movl a0,d7 | restore sign bit to d7 2096 1.1 mrg bra Ld$overflow | else return overflow 2097 1.1 mrg 2098 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 2099 1.1 mrg | bit back into the fraction. 2100 1.1 mrg Ldivdf$a$den: 2101 1.1 mrg movel IMM (1),d4 2102 1.1 mrg andl d6,d0 2103 1.1 mrg 1: addl d1,d1 | shift a left until bit 20 is set 2104 1.1 mrg addxl d0,d0 2105 1.1 mrg #ifndef __mcoldfire__ 2106 1.1 mrg subw IMM (1),d4 | and adjust exponent 2107 1.1 mrg #else 2108 1.1 mrg subl IMM (1),d4 | and adjust exponent 2109 1.1 mrg #endif 2110 1.1 mrg btst IMM (DBL_MANT_DIG-32-1),d0 2111 1.1 mrg bne Ldivdf$1 2112 1.1 mrg bra 1b 2113 1.1 mrg 2114 1.1 mrg Ldivdf$b$den: 2115 1.1 mrg movel IMM (1),d5 2116 1.1 mrg andl d6,d2 2117 1.1 mrg 1: addl d3,d3 | shift b left until bit 20 is set 2118 1.1 mrg addxl d2,d2 2119 1.1 mrg #ifndef __mcoldfire__ 2120 1.1 mrg subw IMM (1),d5 | and adjust exponent 2121 1.1 mrg #else 2122 1.1 mrg subql IMM (1),d5 | and adjust exponent 2123 1.1 mrg #endif 2124 1.1 mrg btst IMM (DBL_MANT_DIG-32-1),d2 2125 1.1 mrg bne Ldivdf$2 2126 1.1 mrg bra 1b 2127 1.1 mrg 2128 1.1 mrg Lround$exit: 2129 1.1 mrg | This is a common exit point for __muldf3 and __divdf3. When they enter 2130 1.1 mrg | this point the sign of the result is in d7, the result in d0-d1, normalized 2131 1.1 mrg | so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4. 2132 1.1 mrg 2133 1.1 mrg | First check for underlow in the exponent: 2134 1.1 mrg #ifndef __mcoldfire__ 2135 1.1 mrg cmpw IMM (-DBL_MANT_DIG-1),d4 2136 1.1 mrg #else 2137 1.1 mrg cmpl IMM (-DBL_MANT_DIG-1),d4 2138 1.1 mrg #endif 2139 1.1 mrg blt Ld$underflow 2140 1.1 mrg | It could happen that the exponent is less than 1, in which case the 2141 1.1 mrg | number is denormalized. In this case we shift right and adjust the 2142 1.1 mrg | exponent until it becomes 1 or the fraction is zero (in the latter case 2143 1.1 mrg | we signal underflow and return zero). 2144 1.1 mrg movel d7,a0 | 2145 1.1 mrg movel IMM (0),d6 | use d6-d7 to collect bits flushed right 2146 1.1 mrg movel d6,d7 | use d6-d7 to collect bits flushed right 2147 1.1 mrg #ifndef __mcoldfire__ 2148 1.1 mrg cmpw IMM (1),d4 | if the exponent is less than 1 we 2149 1.1 mrg #else 2150 1.1 mrg cmpl IMM (1),d4 | if the exponent is less than 1 we 2151 1.1 mrg #endif 2152 1.1 mrg bge 2f | have to shift right (denormalize) 2153 1.1 mrg 1: 2154 1.1 mrg #ifndef __mcoldfire__ 2155 1.1 mrg addw IMM (1),d4 | adjust the exponent 2156 1.1 mrg lsrl IMM (1),d0 | shift right once 2157 1.1 mrg roxrl IMM (1),d1 | 2158 1.1 mrg roxrl IMM (1),d2 | 2159 1.1 mrg roxrl IMM (1),d3 | 2160 1.1 mrg roxrl IMM (1),d6 | 2161 1.1 mrg roxrl IMM (1),d7 | 2162 1.1 mrg cmpw IMM (1),d4 | is the exponent 1 already? 2163 1.1 mrg #else 2164 1.1 mrg addl IMM (1),d4 | adjust the exponent 2165 1.1 mrg lsrl IMM (1),d7 2166 1.1 mrg btst IMM (0),d6 2167 1.1 mrg beq 13f 2168 1.1 mrg bset IMM (31),d7 2169 1.1 mrg 13: lsrl IMM (1),d6 2170 1.1 mrg btst IMM (0),d3 2171 1.1 mrg beq 14f 2172 1.1 mrg bset IMM (31),d6 2173 1.1 mrg 14: lsrl IMM (1),d3 2174 1.1 mrg btst IMM (0),d2 2175 1.1 mrg beq 10f 2176 1.1 mrg bset IMM (31),d3 2177 1.1 mrg 10: lsrl IMM (1),d2 2178 1.1 mrg btst IMM (0),d1 2179 1.1 mrg beq 11f 2180 1.1 mrg bset IMM (31),d2 2181 1.1 mrg 11: lsrl IMM (1),d1 2182 1.1 mrg btst IMM (0),d0 2183 1.1 mrg beq 12f 2184 1.1 mrg bset IMM (31),d1 2185 1.1 mrg 12: lsrl IMM (1),d0 2186 1.1 mrg cmpl IMM (1),d4 | is the exponent 1 already? 2187 1.1 mrg #endif 2188 1.1 mrg beq 2f | if not loop back 2189 1.1 mrg bra 1b | 2190 1.1 mrg bra Ld$underflow | safety check, shouldn't execute ' 2191 1.1 mrg 2: orl d6,d2 | this is a trick so we don't lose ' 2192 1.1 mrg orl d7,d3 | the bits which were flushed right 2193 1.1 mrg movel a0,d7 | get back sign bit into d7 2194 1.1 mrg | Now call the rounding routine (which takes care of denormalized numbers): 2195 1.1 mrg lea pc@(Lround$0),a0 | to return from rounding routine 2196 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 2197 1.1 mrg #ifdef __mcoldfire__ 2198 1.1 mrg clrl d6 2199 1.1 mrg #endif 2200 1.1 mrg movew a1@(6),d6 | rounding mode in d6 2201 1.1 mrg beq Lround$to$nearest 2202 1.1 mrg #ifndef __mcoldfire__ 2203 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 2204 1.1 mrg #else 2205 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 2206 1.1 mrg #endif 2207 1.1 mrg bhi Lround$to$minus 2208 1.1 mrg blt Lround$to$zero 2209 1.1 mrg bra Lround$to$plus 2210 1.1 mrg Lround$0: 2211 1.1 mrg | Here we have a correctly rounded result (either normalized or denormalized). 2212 1.1 mrg 2213 1.1 mrg | Here we should have either a normalized number or a denormalized one, and 2214 1.1 mrg | the exponent is necessarily larger or equal to 1 (so we don't have to ' 2215 1.1 mrg | check again for underflow!). We have to check for overflow or for a 2216 1.1 mrg | denormalized number (which also signals underflow). 2217 1.1 mrg | Check for overflow (i.e., exponent >= 0x7ff). 2218 1.1 mrg #ifndef __mcoldfire__ 2219 1.1 mrg cmpw IMM (0x07ff),d4 2220 1.1 mrg #else 2221 1.1 mrg cmpl IMM (0x07ff),d4 2222 1.1 mrg #endif 2223 1.1 mrg bge Ld$overflow 2224 1.1 mrg | Now check for a denormalized number (exponent==0): 2225 1.1 mrg movew d4,d4 2226 1.1 mrg beq Ld$den 2227 1.1 mrg 1: 2228 1.1 mrg | Put back the exponents and sign and return. 2229 1.1 mrg #ifndef __mcoldfire__ 2230 1.1 mrg lslw IMM (4),d4 | exponent back to fourth byte 2231 1.1 mrg #else 2232 1.1 mrg lsll IMM (4),d4 | exponent back to fourth byte 2233 1.1 mrg #endif 2234 1.1 mrg bclr IMM (DBL_MANT_DIG-32-1),d0 2235 1.1 mrg swap d0 | and put back exponent 2236 1.1 mrg #ifndef __mcoldfire__ 2237 1.1 mrg orw d4,d0 | 2238 1.1 mrg #else 2239 1.1 mrg orl d4,d0 | 2240 1.1 mrg #endif 2241 1.1 mrg swap d0 | 2242 1.1 mrg orl d7,d0 | and sign also 2243 1.1 mrg 2244 1.1 mrg PICLEA SYM (_fpCCR),a0 2245 1.1 mrg movew IMM (0),a0@ 2246 1.1 mrg #ifndef __mcoldfire__ 2247 1.1 mrg moveml sp@+,d2-d7 2248 1.1 mrg #else 2249 1.1 mrg moveml sp@,d2-d7 2250 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2251 1.1 mrg | be adjusted here. 2252 1.1 mrg #endif 2253 1.1 mrg unlk a6 2254 1.1 mrg rts 2255 1.1 mrg 2256 1.1 mrg |============================================================================= 2257 1.1 mrg | __negdf2 2258 1.1 mrg |============================================================================= 2259 1.1 mrg 2260 1.1 mrg | double __negdf2(double, double); 2261 1.1 mrg FUNC(__negdf2) 2262 1.1 mrg SYM (__negdf2): 2263 1.1 mrg #ifndef __mcoldfire__ 2264 1.1 mrg link a6,IMM (0) 2265 1.1 mrg moveml d2-d7,sp@- 2266 1.1 mrg #else 2267 1.1 mrg link a6,IMM (-24) 2268 1.1 mrg moveml d2-d7,sp@ 2269 1.1 mrg #endif 2270 1.1 mrg moveq IMM (NEGATE),d5 2271 1.1 mrg movel a6@(8),d0 | get number to negate in d0-d1 2272 1.1 mrg movel a6@(12),d1 | 2273 1.1 mrg bchg IMM (31),d0 | negate 2274 1.1 mrg movel d0,d2 | make a positive copy (for the tests) 2275 1.1 mrg bclr IMM (31),d2 | 2276 1.1 mrg movel d2,d4 | check for zero 2277 1.1 mrg orl d1,d4 | 2278 1.1 mrg beq 2f | if zero (either sign) return +zero 2279 1.1 mrg cmpl IMM (0x7ff00000),d2 | compare to +INFINITY 2280 1.1 mrg blt 1f | if finite, return 2281 1.1 mrg bhi Ld$inop | if larger (fraction not zero) is NaN 2282 1.1 mrg tstl d1 | if d2 == 0x7ff00000 check d1 2283 1.1 mrg bne Ld$inop | 2284 1.1 mrg movel d0,d7 | else get sign and return INFINITY 2285 1.1 mrg andl IMM (0x80000000),d7 2286 1.1 mrg bra Ld$infty 2287 1.1 mrg 1: PICLEA SYM (_fpCCR),a0 2288 1.1 mrg movew IMM (0),a0@ 2289 1.1 mrg #ifndef __mcoldfire__ 2290 1.1 mrg moveml sp@+,d2-d7 2291 1.1 mrg #else 2292 1.1 mrg moveml sp@,d2-d7 2293 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2294 1.1 mrg | be adjusted here. 2295 1.1 mrg #endif 2296 1.1 mrg unlk a6 2297 1.1 mrg rts 2298 1.1 mrg 2: bclr IMM (31),d0 2299 1.1 mrg bra 1b 2300 1.1 mrg 2301 1.1 mrg |============================================================================= 2302 1.1 mrg | __cmpdf2 2303 1.1 mrg |============================================================================= 2304 1.1 mrg 2305 1.1 mrg GREATER = 1 2306 1.1 mrg LESS = -1 2307 1.1 mrg EQUAL = 0 2308 1.1 mrg 2309 1.1 mrg | int __cmpdf2_internal(double, double, int); 2310 1.1 mrg SYM (__cmpdf2_internal): 2311 1.1 mrg #ifndef __mcoldfire__ 2312 1.1 mrg link a6,IMM (0) 2313 1.1 mrg moveml d2-d7,sp@- | save registers 2314 1.1 mrg #else 2315 1.1 mrg link a6,IMM (-24) 2316 1.1 mrg moveml d2-d7,sp@ 2317 1.1 mrg #endif 2318 1.1 mrg moveq IMM (COMPARE),d5 2319 1.1 mrg movel a6@(8),d0 | get first operand 2320 1.1 mrg movel a6@(12),d1 | 2321 1.1 mrg movel a6@(16),d2 | get second operand 2322 1.1 mrg movel a6@(20),d3 | 2323 1.1 mrg | First check if a and/or b are (+/-) zero and in that case clear 2324 1.1 mrg | the sign bit. 2325 1.1 mrg movel d0,d6 | copy signs into d6 (a) and d7(b) 2326 1.1 mrg bclr IMM (31),d0 | and clear signs in d0 and d2 2327 1.1 mrg movel d2,d7 | 2328 1.1 mrg bclr IMM (31),d2 | 2329 1.1 mrg cmpl IMM (0x7ff00000),d0 | check for a == NaN 2330 1.1 mrg bhi Lcmpd$inop | if d0 > 0x7ff00000, a is NaN 2331 1.1 mrg beq Lcmpdf$a$nf | if equal can be INFINITY, so check d1 2332 1.1 mrg movel d0,d4 | copy into d4 to test for zero 2333 1.1 mrg orl d1,d4 | 2334 1.1 mrg beq Lcmpdf$a$0 | 2335 1.1 mrg Lcmpdf$0: 2336 1.1 mrg cmpl IMM (0x7ff00000),d2 | check for b == NaN 2337 1.1 mrg bhi Lcmpd$inop | if d2 > 0x7ff00000, b is NaN 2338 1.1 mrg beq Lcmpdf$b$nf | if equal can be INFINITY, so check d3 2339 1.1 mrg movel d2,d4 | 2340 1.1 mrg orl d3,d4 | 2341 1.1 mrg beq Lcmpdf$b$0 | 2342 1.1 mrg Lcmpdf$1: 2343 1.1 mrg | Check the signs 2344 1.1 mrg eorl d6,d7 2345 1.1 mrg bpl 1f 2346 1.1 mrg | If the signs are not equal check if a >= 0 2347 1.1 mrg tstl d6 2348 1.1 mrg bpl Lcmpdf$a$gt$b | if (a >= 0 && b < 0) => a > b 2349 1.1 mrg bmi Lcmpdf$b$gt$a | if (a < 0 && b >= 0) => a < b 2350 1.1 mrg 1: 2351 1.1 mrg | If the signs are equal check for < 0 2352 1.1 mrg tstl d6 2353 1.1 mrg bpl 1f 2354 1.1 mrg | If both are negative exchange them 2355 1.1 mrg #ifndef __mcoldfire__ 2356 1.1 mrg exg d0,d2 2357 1.1 mrg exg d1,d3 2358 1.1 mrg #else 2359 1.1 mrg movel d0,d7 2360 1.1 mrg movel d2,d0 2361 1.1 mrg movel d7,d2 2362 1.1 mrg movel d1,d7 2363 1.1 mrg movel d3,d1 2364 1.1 mrg movel d7,d3 2365 1.1 mrg #endif 2366 1.1 mrg 1: 2367 1.1 mrg | Now that they are positive we just compare them as longs (does this also 2368 1.1 mrg | work for denormalized numbers?). 2369 1.1 mrg cmpl d0,d2 2370 1.1 mrg bhi Lcmpdf$b$gt$a | |b| > |a| 2371 1.1 mrg bne Lcmpdf$a$gt$b | |b| < |a| 2372 1.1 mrg | If we got here d0 == d2, so we compare d1 and d3. 2373 1.1 mrg cmpl d1,d3 2374 1.1 mrg bhi Lcmpdf$b$gt$a | |b| > |a| 2375 1.1 mrg bne Lcmpdf$a$gt$b | |b| < |a| 2376 1.1 mrg | If we got here a == b. 2377 1.1 mrg movel IMM (EQUAL),d0 2378 1.1 mrg #ifndef __mcoldfire__ 2379 1.1 mrg moveml sp@+,d2-d7 | put back the registers 2380 1.1 mrg #else 2381 1.1 mrg moveml sp@,d2-d7 2382 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2383 1.1 mrg | be adjusted here. 2384 1.1 mrg #endif 2385 1.1 mrg unlk a6 2386 1.1 mrg rts 2387 1.1 mrg Lcmpdf$a$gt$b: 2388 1.1 mrg movel IMM (GREATER),d0 2389 1.1 mrg #ifndef __mcoldfire__ 2390 1.1 mrg moveml sp@+,d2-d7 | put back the registers 2391 1.1 mrg #else 2392 1.1 mrg moveml sp@,d2-d7 2393 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2394 1.1 mrg | be adjusted here. 2395 1.1 mrg #endif 2396 1.1 mrg unlk a6 2397 1.1 mrg rts 2398 1.1 mrg Lcmpdf$b$gt$a: 2399 1.1 mrg movel IMM (LESS),d0 2400 1.1 mrg #ifndef __mcoldfire__ 2401 1.1 mrg moveml sp@+,d2-d7 | put back the registers 2402 1.1 mrg #else 2403 1.1 mrg moveml sp@,d2-d7 2404 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 2405 1.1 mrg | be adjusted here. 2406 1.1 mrg #endif 2407 1.1 mrg unlk a6 2408 1.1 mrg rts 2409 1.1 mrg 2410 1.1 mrg Lcmpdf$a$0: 2411 1.1 mrg bclr IMM (31),d6 2412 1.1 mrg bra Lcmpdf$0 2413 1.1 mrg Lcmpdf$b$0: 2414 1.1 mrg bclr IMM (31),d7 2415 1.1 mrg bra Lcmpdf$1 2416 1.1 mrg 2417 1.1 mrg Lcmpdf$a$nf: 2418 1.1 mrg tstl d1 2419 1.1 mrg bne Ld$inop 2420 1.1 mrg bra Lcmpdf$0 2421 1.1 mrg 2422 1.1 mrg Lcmpdf$b$nf: 2423 1.1 mrg tstl d3 2424 1.1 mrg bne Ld$inop 2425 1.1 mrg bra Lcmpdf$1 2426 1.1 mrg 2427 1.1 mrg Lcmpd$inop: 2428 1.1 mrg movl a6@(24),d0 2429 1.1 mrg moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 2430 1.1 mrg moveq IMM (DOUBLE_FLOAT),d6 2431 1.1 mrg PICJUMP $_exception_handler 2432 1.1 mrg 2433 1.1 mrg | int __cmpdf2(double, double); 2434 1.1 mrg FUNC(__cmpdf2) 2435 1.1 mrg SYM (__cmpdf2): 2436 1.1 mrg link a6,IMM (0) 2437 1.1 mrg pea 1 2438 1.1 mrg movl a6@(20),sp@- 2439 1.1 mrg movl a6@(16),sp@- 2440 1.1 mrg movl a6@(12),sp@- 2441 1.1 mrg movl a6@(8),sp@- 2442 1.1 mrg PICCALL SYM (__cmpdf2_internal) 2443 1.1 mrg unlk a6 2444 1.1 mrg rts 2445 1.1 mrg 2446 1.1 mrg |============================================================================= 2447 1.1 mrg | rounding routines 2448 1.1 mrg |============================================================================= 2449 1.1 mrg 2450 1.1 mrg | The rounding routines expect the number to be normalized in registers 2451 1.1 mrg | d0-d1-d2-d3, with the exponent in register d4. They assume that the 2452 1.1 mrg | exponent is larger or equal to 1. They return a properly normalized number 2453 1.1 mrg | if possible, and a denormalized number otherwise. The exponent is returned 2454 1.1 mrg | in d4. 2455 1.1 mrg 2456 1.1 mrg Lround$to$nearest: 2457 1.1 mrg | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"): 2458 1.1 mrg | Here we assume that the exponent is not too small (this should be checked 2459 1.1 mrg | before entering the rounding routine), but the number could be denormalized. 2460 1.1 mrg 2461 1.1 mrg | Check for denormalized numbers: 2462 1.1 mrg 1: btst IMM (DBL_MANT_DIG-32),d0 2463 1.1 mrg bne 2f | if set the number is normalized 2464 1.1 mrg | Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent 2465 1.1 mrg | is one (remember that a denormalized number corresponds to an 2466 1.1 mrg | exponent of -D_BIAS+1). 2467 1.1 mrg #ifndef __mcoldfire__ 2468 1.1 mrg cmpw IMM (1),d4 | remember that the exponent is at least one 2469 1.1 mrg #else 2470 1.1 mrg cmpl IMM (1),d4 | remember that the exponent is at least one 2471 1.1 mrg #endif 2472 1.1 mrg beq 2f | an exponent of one means denormalized 2473 1.1 mrg addl d3,d3 | else shift and adjust the exponent 2474 1.1 mrg addxl d2,d2 | 2475 1.1 mrg addxl d1,d1 | 2476 1.1 mrg addxl d0,d0 | 2477 1.1 mrg #ifndef __mcoldfire__ 2478 1.1 mrg dbra d4,1b | 2479 1.1 mrg #else 2480 1.1 mrg subql IMM (1), d4 2481 1.1 mrg bpl 1b 2482 1.1 mrg #endif 2483 1.1 mrg 2: 2484 1.1 mrg | Now round: we do it as follows: after the shifting we can write the 2485 1.1 mrg | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2. 2486 1.1 mrg | If delta < 1, do nothing. If delta > 1, add 1 to f. 2487 1.1 mrg | If delta == 1, we make sure the rounded number will be even (odd?) 2488 1.1 mrg | (after shifting). 2489 1.1 mrg btst IMM (0),d1 | is delta < 1? 2490 1.1 mrg beq 2f | if so, do not do anything 2491 1.1 mrg orl d2,d3 | is delta == 1? 2492 1.1 mrg bne 1f | if so round to even 2493 1.1 mrg movel d1,d3 | 2494 1.1 mrg andl IMM (2),d3 | bit 1 is the last significant bit 2495 1.1 mrg movel IMM (0),d2 | 2496 1.1 mrg addl d3,d1 | 2497 1.1 mrg addxl d2,d0 | 2498 1.1 mrg bra 2f | 2499 1.1 mrg 1: movel IMM (1),d3 | else add 1 2500 1.1 mrg movel IMM (0),d2 | 2501 1.1 mrg addl d3,d1 | 2502 1.1 mrg addxl d2,d0 2503 1.1 mrg | Shift right once (because we used bit #DBL_MANT_DIG-32!). 2504 1.1 mrg 2: 2505 1.1 mrg #ifndef __mcoldfire__ 2506 1.1 mrg lsrl IMM (1),d0 2507 1.1 mrg roxrl IMM (1),d1 2508 1.1 mrg #else 2509 1.1 mrg lsrl IMM (1),d1 2510 1.1 mrg btst IMM (0),d0 2511 1.1 mrg beq 10f 2512 1.1 mrg bset IMM (31),d1 2513 1.1 mrg 10: lsrl IMM (1),d0 2514 1.1 mrg #endif 2515 1.1 mrg 2516 1.1 mrg | Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a 2517 1.1 mrg | 'fraction overflow' ...). 2518 1.1 mrg btst IMM (DBL_MANT_DIG-32),d0 2519 1.1 mrg beq 1f 2520 1.1 mrg #ifndef __mcoldfire__ 2521 1.1 mrg lsrl IMM (1),d0 2522 1.1 mrg roxrl IMM (1),d1 2523 1.1 mrg addw IMM (1),d4 2524 1.1 mrg #else 2525 1.1 mrg lsrl IMM (1),d1 2526 1.1 mrg btst IMM (0),d0 2527 1.1 mrg beq 10f 2528 1.1 mrg bset IMM (31),d1 2529 1.1 mrg 10: lsrl IMM (1),d0 2530 1.1 mrg addl IMM (1),d4 2531 1.1 mrg #endif 2532 1.1 mrg 1: 2533 1.1 mrg | If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we 2534 1.1 mrg | have to put the exponent to zero and return a denormalized number. 2535 1.1 mrg btst IMM (DBL_MANT_DIG-32-1),d0 2536 1.1 mrg beq 1f 2537 1.1 mrg jmp a0@ 2538 1.1 mrg 1: movel IMM (0),d4 2539 1.1 mrg jmp a0@ 2540 1.1 mrg 2541 1.1 mrg Lround$to$zero: 2542 1.1 mrg Lround$to$plus: 2543 1.1 mrg Lround$to$minus: 2544 1.1 mrg jmp a0@ 2545 1.1 mrg #endif /* L_double */ 2546 1.1 mrg 2547 1.1 mrg #ifdef L_float 2548 1.1 mrg 2549 1.1 mrg .globl SYM (_fpCCR) 2550 1.1 mrg .globl $_exception_handler 2551 1.1 mrg 2552 1.1 mrg QUIET_NaN = 0xffffffff 2553 1.1 mrg SIGNL_NaN = 0x7f800001 2554 1.1 mrg INFINITY = 0x7f800000 2555 1.1 mrg 2556 1.1 mrg F_MAX_EXP = 0xff 2557 1.1 mrg F_BIAS = 126 2558 1.1 mrg FLT_MAX_EXP = F_MAX_EXP - F_BIAS 2559 1.1 mrg FLT_MIN_EXP = 1 - F_BIAS 2560 1.1 mrg FLT_MANT_DIG = 24 2561 1.1 mrg 2562 1.1 mrg INEXACT_RESULT = 0x0001 2563 1.1 mrg UNDERFLOW = 0x0002 2564 1.1 mrg OVERFLOW = 0x0004 2565 1.1 mrg DIVIDE_BY_ZERO = 0x0008 2566 1.1 mrg INVALID_OPERATION = 0x0010 2567 1.1 mrg 2568 1.1 mrg SINGLE_FLOAT = 1 2569 1.1 mrg 2570 1.1 mrg NOOP = 0 2571 1.1 mrg ADD = 1 2572 1.1 mrg MULTIPLY = 2 2573 1.1 mrg DIVIDE = 3 2574 1.1 mrg NEGATE = 4 2575 1.1 mrg COMPARE = 5 2576 1.1 mrg EXTENDSFDF = 6 2577 1.1 mrg TRUNCDFSF = 7 2578 1.1 mrg 2579 1.1 mrg UNKNOWN = -1 2580 1.1 mrg ROUND_TO_NEAREST = 0 | round result to nearest representable value 2581 1.1 mrg ROUND_TO_ZERO = 1 | round result towards zero 2582 1.1 mrg ROUND_TO_PLUS = 2 | round result towards plus infinity 2583 1.1 mrg ROUND_TO_MINUS = 3 | round result towards minus infinity 2584 1.1 mrg 2585 1.1 mrg | Entry points: 2586 1.1 mrg 2587 1.1 mrg .globl SYM (__addsf3) 2588 1.1 mrg .globl SYM (__subsf3) 2589 1.1 mrg .globl SYM (__mulsf3) 2590 1.1 mrg .globl SYM (__divsf3) 2591 1.1 mrg .globl SYM (__negsf2) 2592 1.1 mrg .globl SYM (__cmpsf2) 2593 1.1 mrg .globl SYM (__cmpsf2_internal) 2594 1.1 mrg .hidden SYM (__cmpsf2_internal) 2595 1.1 mrg 2596 1.1 mrg | These are common routines to return and signal exceptions. 2597 1.1 mrg 2598 1.1 mrg .text 2599 1.1 mrg .even 2600 1.1 mrg 2601 1.1 mrg Lf$den: 2602 1.1 mrg | Return and signal a denormalized number 2603 1.1 mrg orl d7,d0 2604 1.1 mrg moveq IMM (INEXACT_RESULT+UNDERFLOW),d7 2605 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2606 1.1 mrg PICJUMP $_exception_handler 2607 1.1 mrg 2608 1.1 mrg Lf$infty: 2609 1.1 mrg Lf$overflow: 2610 1.1 mrg | Return a properly signed INFINITY and set the exception flags 2611 1.1 mrg movel IMM (INFINITY),d0 2612 1.1 mrg orl d7,d0 2613 1.1 mrg moveq IMM (INEXACT_RESULT+OVERFLOW),d7 2614 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2615 1.1 mrg PICJUMP $_exception_handler 2616 1.1 mrg 2617 1.1 mrg Lf$underflow: 2618 1.1 mrg | Return 0 and set the exception flags 2619 1.1 mrg moveq IMM (0),d0 2620 1.1 mrg moveq IMM (INEXACT_RESULT+UNDERFLOW),d7 2621 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2622 1.1 mrg PICJUMP $_exception_handler 2623 1.1 mrg 2624 1.1 mrg Lf$inop: 2625 1.1 mrg | Return a quiet NaN and set the exception flags 2626 1.1 mrg movel IMM (QUIET_NaN),d0 2627 1.1 mrg moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 2628 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2629 1.1 mrg PICJUMP $_exception_handler 2630 1.1 mrg 2631 1.1 mrg Lf$div$0: 2632 1.1 mrg | Return a properly signed INFINITY and set the exception flags 2633 1.1 mrg movel IMM (INFINITY),d0 2634 1.1 mrg orl d7,d0 2635 1.1 mrg moveq IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7 2636 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 2637 1.1 mrg PICJUMP $_exception_handler 2638 1.1 mrg 2639 1.1 mrg |============================================================================= 2640 1.1 mrg |============================================================================= 2641 1.1 mrg | single precision routines 2642 1.1 mrg |============================================================================= 2643 1.1 mrg |============================================================================= 2644 1.1 mrg 2645 1.1 mrg | A single precision floating point number (float) has the format: 2646 1.1 mrg | 2647 1.1 mrg | struct _float { 2648 1.1 mrg | unsigned int sign : 1; /* sign bit */ 2649 1.1 mrg | unsigned int exponent : 8; /* exponent, shifted by 126 */ 2650 1.1 mrg | unsigned int fraction : 23; /* fraction */ 2651 1.1 mrg | } float; 2652 1.1 mrg | 2653 1.1 mrg | Thus sizeof(float) = 4 (32 bits). 2654 1.1 mrg | 2655 1.1 mrg | All the routines are callable from C programs, and return the result 2656 1.1 mrg | in the single register d0. They also preserve all registers except 2657 1.1 mrg | d0-d1 and a0-a1. 2658 1.1 mrg 2659 1.1 mrg |============================================================================= 2660 1.1 mrg | __subsf3 2661 1.1 mrg |============================================================================= 2662 1.1 mrg 2663 1.1 mrg | float __subsf3(float, float); 2664 1.1 mrg FUNC(__subsf3) 2665 1.1 mrg SYM (__subsf3): 2666 1.1 mrg bchg IMM (31),sp@(8) | change sign of second operand 2667 1.1 mrg | and fall through 2668 1.1 mrg |============================================================================= 2669 1.1 mrg | __addsf3 2670 1.1 mrg |============================================================================= 2671 1.1 mrg 2672 1.1 mrg | float __addsf3(float, float); 2673 1.1 mrg FUNC(__addsf3) 2674 1.1 mrg SYM (__addsf3): 2675 1.1 mrg #ifndef __mcoldfire__ 2676 1.1 mrg link a6,IMM (0) | everything will be done in registers 2677 1.1 mrg moveml d2-d7,sp@- | save all data registers but d0-d1 2678 1.1 mrg #else 2679 1.1 mrg link a6,IMM (-24) 2680 1.1 mrg moveml d2-d7,sp@ 2681 1.1 mrg #endif 2682 1.1 mrg movel a6@(8),d0 | get first operand 2683 1.1 mrg movel a6@(12),d1 | get second operand 2684 1.1 mrg movel d0,a0 | get d0's sign bit ' 2685 1.1 mrg addl d0,d0 | check and clear sign bit of a 2686 1.1 mrg beq Laddsf$b | if zero return second operand 2687 1.1 mrg movel d1,a1 | save b's sign bit ' 2688 1.1 mrg addl d1,d1 | get rid of sign bit 2689 1.1 mrg beq Laddsf$a | if zero return first operand 2690 1.1 mrg 2691 1.1 mrg | Get the exponents and check for denormalized and/or infinity. 2692 1.1 mrg 2693 1.1 mrg movel IMM (0x00ffffff),d4 | mask to get fraction 2694 1.1 mrg movel IMM (0x01000000),d5 | mask to put hidden bit back 2695 1.1 mrg 2696 1.1 mrg movel d0,d6 | save a to get exponent 2697 1.1 mrg andl d4,d0 | get fraction in d0 2698 1.1 mrg notl d4 | make d4 into a mask for the exponent 2699 1.1 mrg andl d4,d6 | get exponent in d6 2700 1.1 mrg beq Laddsf$a$den | branch if a is denormalized 2701 1.1 mrg cmpl d4,d6 | check for INFINITY or NaN 2702 1.1 mrg beq Laddsf$nf 2703 1.1 mrg swap d6 | put exponent into first word 2704 1.1 mrg orl d5,d0 | and put hidden bit back 2705 1.1 mrg Laddsf$1: 2706 1.1 mrg | Now we have a's exponent in d6 (second byte) and the mantissa in d0. ' 2707 1.1 mrg movel d1,d7 | get exponent in d7 2708 1.1 mrg andl d4,d7 | 2709 1.1 mrg beq Laddsf$b$den | branch if b is denormalized 2710 1.1 mrg cmpl d4,d7 | check for INFINITY or NaN 2711 1.1 mrg beq Laddsf$nf 2712 1.1 mrg swap d7 | put exponent into first word 2713 1.1 mrg notl d4 | make d4 into a mask for the fraction 2714 1.1 mrg andl d4,d1 | get fraction in d1 2715 1.1 mrg orl d5,d1 | and put hidden bit back 2716 1.1 mrg Laddsf$2: 2717 1.1 mrg | Now we have b's exponent in d7 (second byte) and the mantissa in d1. ' 2718 1.1 mrg 2719 1.1 mrg | Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we 2720 1.1 mrg | shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra 2721 1.1 mrg | bit). 2722 1.1 mrg 2723 1.1 mrg movel d1,d2 | move b to d2, since we want to use 2724 1.1 mrg | two registers to do the sum 2725 1.1 mrg movel IMM (0),d1 | and clear the new ones 2726 1.1 mrg movel d1,d3 | 2727 1.1 mrg 2728 1.1 mrg | Here we shift the numbers in registers d0 and d1 so the exponents are the 2729 1.1 mrg | same, and put the largest exponent in d6. Note that we are using two 2730 1.1 mrg | registers for each number (see the discussion by D. Knuth in "Seminumerical 2731 1.1 mrg | Algorithms"). 2732 1.1 mrg #ifndef __mcoldfire__ 2733 1.1 mrg cmpw d6,d7 | compare exponents 2734 1.1 mrg #else 2735 1.1 mrg cmpl d6,d7 | compare exponents 2736 1.1 mrg #endif 2737 1.1 mrg beq Laddsf$3 | if equal don't shift ' 2738 1.1 mrg bhi 5f | branch if second exponent largest 2739 1.1 mrg 1: 2740 1.1 mrg subl d6,d7 | keep the largest exponent 2741 1.1 mrg negl d7 2742 1.1 mrg #ifndef __mcoldfire__ 2743 1.1 mrg lsrw IMM (8),d7 | put difference in lower byte 2744 1.1 mrg #else 2745 1.1 mrg lsrl IMM (8),d7 | put difference in lower byte 2746 1.1 mrg #endif 2747 1.1 mrg | if difference is too large we don't shift (actually, we can just exit) ' 2748 1.1 mrg #ifndef __mcoldfire__ 2749 1.1 mrg cmpw IMM (FLT_MANT_DIG+2),d7 2750 1.1 mrg #else 2751 1.1 mrg cmpl IMM (FLT_MANT_DIG+2),d7 2752 1.1 mrg #endif 2753 1.1 mrg bge Laddsf$b$small 2754 1.1 mrg #ifndef __mcoldfire__ 2755 1.1 mrg cmpw IMM (16),d7 | if difference >= 16 swap 2756 1.1 mrg #else 2757 1.1 mrg cmpl IMM (16),d7 | if difference >= 16 swap 2758 1.1 mrg #endif 2759 1.1 mrg bge 4f 2760 1.1 mrg 2: 2761 1.1 mrg #ifndef __mcoldfire__ 2762 1.1 mrg subw IMM (1),d7 2763 1.1 mrg #else 2764 1.1 mrg subql IMM (1), d7 2765 1.1 mrg #endif 2766 1.1 mrg 3: 2767 1.1 mrg #ifndef __mcoldfire__ 2768 1.1 mrg lsrl IMM (1),d2 | shift right second operand 2769 1.1 mrg roxrl IMM (1),d3 2770 1.1 mrg dbra d7,3b 2771 1.1 mrg #else 2772 1.1 mrg lsrl IMM (1),d3 2773 1.1 mrg btst IMM (0),d2 2774 1.1 mrg beq 10f 2775 1.1 mrg bset IMM (31),d3 2776 1.1 mrg 10: lsrl IMM (1),d2 2777 1.1 mrg subql IMM (1), d7 2778 1.1 mrg bpl 3b 2779 1.1 mrg #endif 2780 1.1 mrg bra Laddsf$3 2781 1.1 mrg 4: 2782 1.1 mrg movew d2,d3 2783 1.1 mrg swap d3 2784 1.1 mrg movew d3,d2 2785 1.1 mrg swap d2 2786 1.1 mrg #ifndef __mcoldfire__ 2787 1.1 mrg subw IMM (16),d7 2788 1.1 mrg #else 2789 1.1 mrg subl IMM (16),d7 2790 1.1 mrg #endif 2791 1.1 mrg bne 2b | if still more bits, go back to normal case 2792 1.1 mrg bra Laddsf$3 2793 1.1 mrg 5: 2794 1.1 mrg #ifndef __mcoldfire__ 2795 1.1 mrg exg d6,d7 | exchange the exponents 2796 1.1 mrg #else 2797 1.1 mrg eorl d6,d7 2798 1.1 mrg eorl d7,d6 2799 1.1 mrg eorl d6,d7 2800 1.1 mrg #endif 2801 1.1 mrg subl d6,d7 | keep the largest exponent 2802 1.1 mrg negl d7 | 2803 1.1 mrg #ifndef __mcoldfire__ 2804 1.1 mrg lsrw IMM (8),d7 | put difference in lower byte 2805 1.1 mrg #else 2806 1.1 mrg lsrl IMM (8),d7 | put difference in lower byte 2807 1.1 mrg #endif 2808 1.1 mrg | if difference is too large we don't shift (and exit!) ' 2809 1.1 mrg #ifndef __mcoldfire__ 2810 1.1 mrg cmpw IMM (FLT_MANT_DIG+2),d7 2811 1.1 mrg #else 2812 1.1 mrg cmpl IMM (FLT_MANT_DIG+2),d7 2813 1.1 mrg #endif 2814 1.1 mrg bge Laddsf$a$small 2815 1.1 mrg #ifndef __mcoldfire__ 2816 1.1 mrg cmpw IMM (16),d7 | if difference >= 16 swap 2817 1.1 mrg #else 2818 1.1 mrg cmpl IMM (16),d7 | if difference >= 16 swap 2819 1.1 mrg #endif 2820 1.1 mrg bge 8f 2821 1.1 mrg 6: 2822 1.1 mrg #ifndef __mcoldfire__ 2823 1.1 mrg subw IMM (1),d7 2824 1.1 mrg #else 2825 1.1 mrg subl IMM (1),d7 2826 1.1 mrg #endif 2827 1.1 mrg 7: 2828 1.1 mrg #ifndef __mcoldfire__ 2829 1.1 mrg lsrl IMM (1),d0 | shift right first operand 2830 1.1 mrg roxrl IMM (1),d1 2831 1.1 mrg dbra d7,7b 2832 1.1 mrg #else 2833 1.1 mrg lsrl IMM (1),d1 2834 1.1 mrg btst IMM (0),d0 2835 1.1 mrg beq 10f 2836 1.1 mrg bset IMM (31),d1 2837 1.1 mrg 10: lsrl IMM (1),d0 2838 1.1 mrg subql IMM (1),d7 2839 1.1 mrg bpl 7b 2840 1.1 mrg #endif 2841 1.1 mrg bra Laddsf$3 2842 1.1 mrg 8: 2843 1.1 mrg movew d0,d1 2844 1.1 mrg swap d1 2845 1.1 mrg movew d1,d0 2846 1.1 mrg swap d0 2847 1.1 mrg #ifndef __mcoldfire__ 2848 1.1 mrg subw IMM (16),d7 2849 1.1 mrg #else 2850 1.1 mrg subl IMM (16),d7 2851 1.1 mrg #endif 2852 1.1 mrg bne 6b | if still more bits, go back to normal case 2853 1.1 mrg | otherwise we fall through 2854 1.1 mrg 2855 1.1 mrg | Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the 2856 1.1 mrg | signs are stored in a0 and a1). 2857 1.1 mrg 2858 1.1 mrg Laddsf$3: 2859 1.1 mrg | Here we have to decide whether to add or subtract the numbers 2860 1.1 mrg #ifndef __mcoldfire__ 2861 1.1 mrg exg d6,a0 | get signs back 2862 1.1 mrg exg d7,a1 | and save the exponents 2863 1.1 mrg #else 2864 1.1 mrg movel d6,d4 2865 1.1 mrg movel a0,d6 2866 1.1 mrg movel d4,a0 2867 1.1 mrg movel d7,d4 2868 1.1 mrg movel a1,d7 2869 1.1 mrg movel d4,a1 2870 1.1 mrg #endif 2871 1.1 mrg eorl d6,d7 | combine sign bits 2872 1.1 mrg bmi Lsubsf$0 | if negative a and b have opposite 2873 1.1 mrg | sign so we actually subtract the 2874 1.1 mrg | numbers 2875 1.1 mrg 2876 1.1 mrg | Here we have both positive or both negative 2877 1.1 mrg #ifndef __mcoldfire__ 2878 1.1 mrg exg d6,a0 | now we have the exponent in d6 2879 1.1 mrg #else 2880 1.1 mrg movel d6,d4 2881 1.1 mrg movel a0,d6 2882 1.1 mrg movel d4,a0 2883 1.1 mrg #endif 2884 1.1 mrg movel a0,d7 | and sign in d7 2885 1.1 mrg andl IMM (0x80000000),d7 2886 1.1 mrg | Here we do the addition. 2887 1.1 mrg addl d3,d1 2888 1.1 mrg addxl d2,d0 2889 1.1 mrg | Note: now we have d2, d3, d4 and d5 to play with! 2890 1.1 mrg 2891 1.1 mrg | Put the exponent, in the first byte, in d2, to use the "standard" rounding 2892 1.1 mrg | routines: 2893 1.1 mrg movel d6,d2 2894 1.1 mrg #ifndef __mcoldfire__ 2895 1.1 mrg lsrw IMM (8),d2 2896 1.1 mrg #else 2897 1.1 mrg lsrl IMM (8),d2 2898 1.1 mrg #endif 2899 1.1 mrg 2900 1.1 mrg | Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider 2901 1.1 mrg | the case of denormalized numbers in the rounding routine itself). 2902 1.1 mrg | As in the addition (not in the subtraction!) we could have set 2903 1.1 mrg | one more bit we check this: 2904 1.1 mrg btst IMM (FLT_MANT_DIG+1),d0 2905 1.1 mrg beq 1f 2906 1.1 mrg #ifndef __mcoldfire__ 2907 1.1 mrg lsrl IMM (1),d0 2908 1.1 mrg roxrl IMM (1),d1 2909 1.1 mrg #else 2910 1.1 mrg lsrl IMM (1),d1 2911 1.1 mrg btst IMM (0),d0 2912 1.1 mrg beq 10f 2913 1.1 mrg bset IMM (31),d1 2914 1.1 mrg 10: lsrl IMM (1),d0 2915 1.1 mrg #endif 2916 1.1 mrg addl IMM (1),d2 2917 1.1 mrg 1: 2918 1.1 mrg lea pc@(Laddsf$4),a0 | to return from rounding routine 2919 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 2920 1.1 mrg #ifdef __mcoldfire__ 2921 1.1 mrg clrl d6 2922 1.1 mrg #endif 2923 1.1 mrg movew a1@(6),d6 | rounding mode in d6 2924 1.1 mrg beq Lround$to$nearest 2925 1.1 mrg #ifndef __mcoldfire__ 2926 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 2927 1.1 mrg #else 2928 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 2929 1.1 mrg #endif 2930 1.1 mrg bhi Lround$to$minus 2931 1.1 mrg blt Lround$to$zero 2932 1.1 mrg bra Lround$to$plus 2933 1.1 mrg Laddsf$4: 2934 1.1 mrg | Put back the exponent, but check for overflow. 2935 1.1 mrg #ifndef __mcoldfire__ 2936 1.1 mrg cmpw IMM (0xff),d2 2937 1.1 mrg #else 2938 1.1 mrg cmpl IMM (0xff),d2 2939 1.1 mrg #endif 2940 1.11 mrg bge 1f 2941 1.1 mrg bclr IMM (FLT_MANT_DIG-1),d0 2942 1.1 mrg #ifndef __mcoldfire__ 2943 1.1 mrg lslw IMM (7),d2 2944 1.1 mrg #else 2945 1.1 mrg lsll IMM (7),d2 2946 1.1 mrg #endif 2947 1.1 mrg swap d2 2948 1.1 mrg orl d2,d0 2949 1.1 mrg bra Laddsf$ret 2950 1.1 mrg 1: 2951 1.1 mrg moveq IMM (ADD),d5 2952 1.1 mrg bra Lf$overflow 2953 1.1 mrg 2954 1.1 mrg Lsubsf$0: 2955 1.1 mrg | We are here if a > 0 and b < 0 (sign bits cleared). 2956 1.1 mrg | Here we do the subtraction. 2957 1.1 mrg movel d6,d7 | put sign in d7 2958 1.1 mrg andl IMM (0x80000000),d7 2959 1.1 mrg 2960 1.1 mrg subl d3,d1 | result in d0-d1 2961 1.1 mrg subxl d2,d0 | 2962 1.1 mrg beq Laddsf$ret | if zero just exit 2963 1.1 mrg bpl 1f | if positive skip the following 2964 1.1 mrg bchg IMM (31),d7 | change sign bit in d7 2965 1.1 mrg negl d1 2966 1.1 mrg negxl d0 2967 1.1 mrg 1: 2968 1.1 mrg #ifndef __mcoldfire__ 2969 1.1 mrg exg d2,a0 | now we have the exponent in d2 2970 1.1 mrg lsrw IMM (8),d2 | put it in the first byte 2971 1.1 mrg #else 2972 1.1 mrg movel d2,d4 2973 1.1 mrg movel a0,d2 2974 1.1 mrg movel d4,a0 2975 1.1 mrg lsrl IMM (8),d2 | put it in the first byte 2976 1.1 mrg #endif 2977 1.1 mrg 2978 1.1 mrg | Now d0-d1 is positive and the sign bit is in d7. 2979 1.1 mrg 2980 1.1 mrg | Note that we do not have to normalize, since in the subtraction bit 2981 1.1 mrg | #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by 2982 1.1 mrg | the rounding routines themselves. 2983 1.1 mrg lea pc@(Lsubsf$1),a0 | to return from rounding routine 2984 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 2985 1.1 mrg #ifdef __mcoldfire__ 2986 1.1 mrg clrl d6 2987 1.1 mrg #endif 2988 1.1 mrg movew a1@(6),d6 | rounding mode in d6 2989 1.1 mrg beq Lround$to$nearest 2990 1.1 mrg #ifndef __mcoldfire__ 2991 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 2992 1.1 mrg #else 2993 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 2994 1.1 mrg #endif 2995 1.1 mrg bhi Lround$to$minus 2996 1.1 mrg blt Lround$to$zero 2997 1.1 mrg bra Lround$to$plus 2998 1.1 mrg Lsubsf$1: 2999 1.1 mrg | Put back the exponent (we can't have overflow!). ' 3000 1.1 mrg bclr IMM (FLT_MANT_DIG-1),d0 3001 1.1 mrg #ifndef __mcoldfire__ 3002 1.1 mrg lslw IMM (7),d2 3003 1.1 mrg #else 3004 1.1 mrg lsll IMM (7),d2 3005 1.1 mrg #endif 3006 1.1 mrg swap d2 3007 1.1 mrg orl d2,d0 3008 1.1 mrg bra Laddsf$ret 3009 1.1 mrg 3010 1.1 mrg | If one of the numbers was too small (difference of exponents >= 3011 1.1 mrg | FLT_MANT_DIG+2) we return the other (and now we don't have to ' 3012 1.1 mrg | check for finiteness or zero). 3013 1.1 mrg Laddsf$a$small: 3014 1.1 mrg movel a6@(12),d0 3015 1.1 mrg PICLEA SYM (_fpCCR),a0 3016 1.1 mrg movew IMM (0),a0@ 3017 1.1 mrg #ifndef __mcoldfire__ 3018 1.1 mrg moveml sp@+,d2-d7 | restore data registers 3019 1.1 mrg #else 3020 1.1 mrg moveml sp@,d2-d7 3021 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3022 1.1 mrg | be adjusted here. 3023 1.1 mrg #endif 3024 1.1 mrg unlk a6 | and return 3025 1.1 mrg rts 3026 1.1 mrg 3027 1.1 mrg Laddsf$b$small: 3028 1.1 mrg movel a6@(8),d0 3029 1.1 mrg PICLEA SYM (_fpCCR),a0 3030 1.1 mrg movew IMM (0),a0@ 3031 1.1 mrg #ifndef __mcoldfire__ 3032 1.1 mrg moveml sp@+,d2-d7 | restore data registers 3033 1.1 mrg #else 3034 1.1 mrg moveml sp@,d2-d7 3035 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3036 1.1 mrg | be adjusted here. 3037 1.1 mrg #endif 3038 1.1 mrg unlk a6 | and return 3039 1.1 mrg rts 3040 1.1 mrg 3041 1.1 mrg | If the numbers are denormalized remember to put exponent equal to 1. 3042 1.1 mrg 3043 1.1 mrg Laddsf$a$den: 3044 1.1 mrg movel d5,d6 | d5 contains 0x01000000 3045 1.1 mrg swap d6 3046 1.1 mrg bra Laddsf$1 3047 1.1 mrg 3048 1.1 mrg Laddsf$b$den: 3049 1.1 mrg movel d5,d7 3050 1.1 mrg swap d7 3051 1.1 mrg notl d4 | make d4 into a mask for the fraction 3052 1.1 mrg | (this was not executed after the jump) 3053 1.1 mrg bra Laddsf$2 3054 1.1 mrg 3055 1.1 mrg | The rest is mainly code for the different results which can be 3056 1.1 mrg | returned (checking always for +/-INFINITY and NaN). 3057 1.1 mrg 3058 1.1 mrg Laddsf$b: 3059 1.1 mrg | Return b (if a is zero). 3060 1.1 mrg movel a6@(12),d0 3061 1.1 mrg cmpl IMM (0x80000000),d0 | Check if b is -0 3062 1.1 mrg bne 1f 3063 1.1 mrg movel a0,d7 3064 1.1 mrg andl IMM (0x80000000),d7 | Use the sign of a 3065 1.1 mrg clrl d0 3066 1.1 mrg bra Laddsf$ret 3067 1.1 mrg Laddsf$a: 3068 1.1 mrg | Return a (if b is zero). 3069 1.1 mrg movel a6@(8),d0 3070 1.1 mrg 1: 3071 1.1 mrg moveq IMM (ADD),d5 3072 1.1 mrg | We have to check for NaN and +/-infty. 3073 1.1 mrg movel d0,d7 3074 1.1 mrg andl IMM (0x80000000),d7 | put sign in d7 3075 1.1 mrg bclr IMM (31),d0 | clear sign 3076 1.1 mrg cmpl IMM (INFINITY),d0 | check for infty or NaN 3077 1.1 mrg bge 2f 3078 1.1 mrg movel d0,d0 | check for zero (we do this because we don't ' 3079 1.1 mrg bne Laddsf$ret | want to return -0 by mistake 3080 1.1 mrg bclr IMM (31),d7 | if zero be sure to clear sign 3081 1.1 mrg bra Laddsf$ret | if everything OK just return 3082 1.1 mrg 2: 3083 1.1 mrg | The value to be returned is either +/-infty or NaN 3084 1.1 mrg andl IMM (0x007fffff),d0 | check for NaN 3085 1.1 mrg bne Lf$inop | if mantissa not zero is NaN 3086 1.1 mrg bra Lf$infty 3087 1.1 mrg 3088 1.1 mrg Laddsf$ret: 3089 1.1 mrg | Normal exit (a and b nonzero, result is not NaN nor +/-infty). 3090 1.1 mrg | We have to clear the exception flags (just the exception type). 3091 1.1 mrg PICLEA SYM (_fpCCR),a0 3092 1.1 mrg movew IMM (0),a0@ 3093 1.1 mrg orl d7,d0 | put sign bit 3094 1.1 mrg #ifndef __mcoldfire__ 3095 1.1 mrg moveml sp@+,d2-d7 | restore data registers 3096 1.1 mrg #else 3097 1.1 mrg moveml sp@,d2-d7 3098 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3099 1.1 mrg | be adjusted here. 3100 1.1 mrg #endif 3101 1.1 mrg unlk a6 | and return 3102 1.1 mrg rts 3103 1.1 mrg 3104 1.1 mrg Laddsf$ret$den: 3105 1.1 mrg | Return a denormalized number (for addition we don't signal underflow) ' 3106 1.1 mrg lsrl IMM (1),d0 | remember to shift right back once 3107 1.1 mrg bra Laddsf$ret | and return 3108 1.1 mrg 3109 1.1 mrg | Note: when adding two floats of the same sign if either one is 3110 1.1 mrg | NaN we return NaN without regard to whether the other is finite or 3111 1.1 mrg | not. When subtracting them (i.e., when adding two numbers of 3112 1.1 mrg | opposite signs) things are more complicated: if both are INFINITY 3113 1.1 mrg | we return NaN, if only one is INFINITY and the other is NaN we return 3114 1.1 mrg | NaN, but if it is finite we return INFINITY with the corresponding sign. 3115 1.1 mrg 3116 1.1 mrg Laddsf$nf: 3117 1.1 mrg moveq IMM (ADD),d5 3118 1.1 mrg | This could be faster but it is not worth the effort, since it is not 3119 1.1 mrg | executed very often. We sacrifice speed for clarity here. 3120 1.1 mrg movel a6@(8),d0 | get the numbers back (remember that we 3121 1.1 mrg movel a6@(12),d1 | did some processing already) 3122 1.1 mrg movel IMM (INFINITY),d4 | useful constant (INFINITY) 3123 1.1 mrg movel d0,d2 | save sign bits 3124 1.8 mrg movel d0,d7 | into d7 as well as we may need the sign 3125 1.8 mrg | bit before jumping to LfSinfty 3126 1.1 mrg movel d1,d3 3127 1.1 mrg bclr IMM (31),d0 | clear sign bits 3128 1.1 mrg bclr IMM (31),d1 3129 1.1 mrg | We know that one of them is either NaN of +/-INFINITY 3130 1.1 mrg | Check for NaN (if either one is NaN return NaN) 3131 1.1 mrg cmpl d4,d0 | check first a (d0) 3132 1.1 mrg bhi Lf$inop 3133 1.1 mrg cmpl d4,d1 | check now b (d1) 3134 1.1 mrg bhi Lf$inop 3135 1.1 mrg | Now comes the check for +/-INFINITY. We know that both are (maybe not 3136 1.1 mrg | finite) numbers, but we have to check if both are infinite whether we 3137 1.1 mrg | are adding or subtracting them. 3138 1.1 mrg eorl d3,d2 | to check sign bits 3139 1.1 mrg bmi 1f 3140 1.1 mrg andl IMM (0x80000000),d7 | get (common) sign bit 3141 1.1 mrg bra Lf$infty 3142 1.1 mrg 1: 3143 1.1 mrg | We know one (or both) are infinite, so we test for equality between the 3144 1.1 mrg | two numbers (if they are equal they have to be infinite both, so we 3145 1.1 mrg | return NaN). 3146 1.1 mrg cmpl d1,d0 | are both infinite? 3147 1.1 mrg beq Lf$inop | if so return NaN 3148 1.1 mrg 3149 1.1 mrg andl IMM (0x80000000),d7 | get a's sign bit ' 3150 1.1 mrg cmpl d4,d0 | test now for infinity 3151 1.1 mrg beq Lf$infty | if a is INFINITY return with this sign 3152 1.1 mrg bchg IMM (31),d7 | else we know b is INFINITY and has 3153 1.1 mrg bra Lf$infty | the opposite sign 3154 1.1 mrg 3155 1.1 mrg |============================================================================= 3156 1.1 mrg | __mulsf3 3157 1.1 mrg |============================================================================= 3158 1.1 mrg 3159 1.1 mrg | float __mulsf3(float, float); 3160 1.1 mrg FUNC(__mulsf3) 3161 1.1 mrg SYM (__mulsf3): 3162 1.1 mrg #ifndef __mcoldfire__ 3163 1.1 mrg link a6,IMM (0) 3164 1.1 mrg moveml d2-d7,sp@- 3165 1.1 mrg #else 3166 1.1 mrg link a6,IMM (-24) 3167 1.1 mrg moveml d2-d7,sp@ 3168 1.1 mrg #endif 3169 1.1 mrg movel a6@(8),d0 | get a into d0 3170 1.1 mrg movel a6@(12),d1 | and b into d1 3171 1.1 mrg movel d0,d7 | d7 will hold the sign of the product 3172 1.1 mrg eorl d1,d7 | 3173 1.1 mrg andl IMM (0x80000000),d7 3174 1.1 mrg movel IMM (INFINITY),d6 | useful constant (+INFINITY) 3175 1.1 mrg movel d6,d5 | another (mask for fraction) 3176 1.1 mrg notl d5 | 3177 1.1 mrg movel IMM (0x00800000),d4 | this is to put hidden bit back 3178 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 3179 1.1 mrg movel d0,d2 | 3180 1.1 mrg beq Lmulsf$a$0 | branch if a is zero 3181 1.1 mrg bclr IMM (31),d1 | get rid of b's sign bit ' 3182 1.1 mrg movel d1,d3 | 3183 1.1 mrg beq Lmulsf$b$0 | branch if b is zero 3184 1.1 mrg cmpl d6,d0 | is a big? 3185 1.1 mrg bhi Lmulsf$inop | if a is NaN return NaN 3186 1.1 mrg beq Lmulsf$inf | if a is INFINITY we have to check b 3187 1.1 mrg cmpl d6,d1 | now compare b with INFINITY 3188 1.1 mrg bhi Lmulsf$inop | is b NaN? 3189 1.1 mrg beq Lmulsf$overflow | is b INFINITY? 3190 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 3191 1.1 mrg | Now we get the exponents into d2 and d3. 3192 1.1 mrg andl d6,d2 | and isolate exponent in d2 3193 1.1 mrg beq Lmulsf$a$den | if exponent is zero we have a denormalized 3194 1.1 mrg andl d5,d0 | and isolate fraction 3195 1.1 mrg orl d4,d0 | and put hidden bit back 3196 1.1 mrg swap d2 | I like exponents in the first byte 3197 1.1 mrg #ifndef __mcoldfire__ 3198 1.1 mrg lsrw IMM (7),d2 | 3199 1.1 mrg #else 3200 1.1 mrg lsrl IMM (7),d2 | 3201 1.1 mrg #endif 3202 1.1 mrg Lmulsf$1: | number 3203 1.1 mrg andl d6,d3 | 3204 1.1 mrg beq Lmulsf$b$den | 3205 1.1 mrg andl d5,d1 | 3206 1.1 mrg orl d4,d1 | 3207 1.1 mrg swap d3 | 3208 1.1 mrg #ifndef __mcoldfire__ 3209 1.1 mrg lsrw IMM (7),d3 | 3210 1.1 mrg #else 3211 1.1 mrg lsrl IMM (7),d3 | 3212 1.1 mrg #endif 3213 1.1 mrg Lmulsf$2: | 3214 1.1 mrg #ifndef __mcoldfire__ 3215 1.1 mrg addw d3,d2 | add exponents 3216 1.1 mrg subw IMM (F_BIAS+1),d2 | and subtract bias (plus one) 3217 1.1 mrg #else 3218 1.1 mrg addl d3,d2 | add exponents 3219 1.1 mrg subl IMM (F_BIAS+1),d2 | and subtract bias (plus one) 3220 1.1 mrg #endif 3221 1.1 mrg 3222 1.1 mrg | We are now ready to do the multiplication. The situation is as follows: 3223 1.1 mrg | both a and b have bit FLT_MANT_DIG-1 set (even if they were 3224 1.1 mrg | denormalized to start with!), which means that in the product 3225 1.1 mrg | bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the 3226 1.1 mrg | high long) is set. 3227 1.1 mrg 3228 1.1 mrg | To do the multiplication let us move the number a little bit around ... 3229 1.1 mrg movel d1,d6 | second operand in d6 3230 1.1 mrg movel d0,d5 | first operand in d4-d5 3231 1.1 mrg movel IMM (0),d4 3232 1.1 mrg movel d4,d1 | the sums will go in d0-d1 3233 1.1 mrg movel d4,d0 3234 1.1 mrg 3235 1.1 mrg | now bit FLT_MANT_DIG-1 becomes bit 31: 3236 1.1 mrg lsll IMM (31-FLT_MANT_DIG+1),d6 3237 1.1 mrg 3238 1.1 mrg | Start the loop (we loop #FLT_MANT_DIG times): 3239 1.1 mrg moveq IMM (FLT_MANT_DIG-1),d3 3240 1.1 mrg 1: addl d1,d1 | shift sum 3241 1.1 mrg addxl d0,d0 3242 1.1 mrg lsll IMM (1),d6 | get bit bn 3243 1.1 mrg bcc 2f | if not set skip sum 3244 1.1 mrg addl d5,d1 | add a 3245 1.1 mrg addxl d4,d0 3246 1.1 mrg 2: 3247 1.1 mrg #ifndef __mcoldfire__ 3248 1.1 mrg dbf d3,1b | loop back 3249 1.1 mrg #else 3250 1.1 mrg subql IMM (1),d3 3251 1.1 mrg bpl 1b 3252 1.1 mrg #endif 3253 1.1 mrg 3254 1.1 mrg | Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG 3255 1.1 mrg | (mod 32) of d0 set. The first thing to do now is to normalize it so bit 3256 1.1 mrg | FLT_MANT_DIG is set (to do the rounding). 3257 1.1 mrg #ifndef __mcoldfire__ 3258 1.1 mrg rorl IMM (6),d1 3259 1.1 mrg swap d1 3260 1.1 mrg movew d1,d3 3261 1.1 mrg andw IMM (0x03ff),d3 3262 1.1 mrg andw IMM (0xfd00),d1 3263 1.1 mrg #else 3264 1.1 mrg movel d1,d3 3265 1.1 mrg lsll IMM (8),d1 3266 1.1 mrg addl d1,d1 3267 1.1 mrg addl d1,d1 3268 1.1 mrg moveq IMM (22),d5 3269 1.1 mrg lsrl d5,d3 3270 1.1 mrg orl d3,d1 3271 1.1 mrg andl IMM (0xfffffd00),d1 3272 1.1 mrg #endif 3273 1.1 mrg lsll IMM (8),d0 3274 1.1 mrg addl d0,d0 3275 1.1 mrg addl d0,d0 3276 1.1 mrg #ifndef __mcoldfire__ 3277 1.1 mrg orw d3,d0 3278 1.1 mrg #else 3279 1.1 mrg orl d3,d0 3280 1.1 mrg #endif 3281 1.1 mrg 3282 1.1 mrg moveq IMM (MULTIPLY),d5 3283 1.1 mrg 3284 1.1 mrg btst IMM (FLT_MANT_DIG+1),d0 3285 1.1 mrg beq Lround$exit 3286 1.1 mrg #ifndef __mcoldfire__ 3287 1.1 mrg lsrl IMM (1),d0 3288 1.1 mrg roxrl IMM (1),d1 3289 1.1 mrg addw IMM (1),d2 3290 1.1 mrg #else 3291 1.1 mrg lsrl IMM (1),d1 3292 1.1 mrg btst IMM (0),d0 3293 1.1 mrg beq 10f 3294 1.1 mrg bset IMM (31),d1 3295 1.1 mrg 10: lsrl IMM (1),d0 3296 1.1 mrg addql IMM (1),d2 3297 1.1 mrg #endif 3298 1.1 mrg bra Lround$exit 3299 1.1 mrg 3300 1.1 mrg Lmulsf$inop: 3301 1.1 mrg moveq IMM (MULTIPLY),d5 3302 1.1 mrg bra Lf$inop 3303 1.1 mrg 3304 1.1 mrg Lmulsf$overflow: 3305 1.1 mrg moveq IMM (MULTIPLY),d5 3306 1.1 mrg bra Lf$overflow 3307 1.1 mrg 3308 1.1 mrg Lmulsf$inf: 3309 1.1 mrg moveq IMM (MULTIPLY),d5 3310 1.1 mrg | If either is NaN return NaN; else both are (maybe infinite) numbers, so 3311 1.1 mrg | return INFINITY with the correct sign (which is in d7). 3312 1.1 mrg cmpl d6,d1 | is b NaN? 3313 1.1 mrg bhi Lf$inop | if so return NaN 3314 1.1 mrg bra Lf$overflow | else return +/-INFINITY 3315 1.1 mrg 3316 1.1 mrg | If either number is zero return zero, unless the other is +/-INFINITY, 3317 1.1 mrg | or NaN, in which case we return NaN. 3318 1.1 mrg Lmulsf$b$0: 3319 1.1 mrg | Here d1 (==b) is zero. 3320 1.1 mrg movel a6@(8),d1 | get a again to check for non-finiteness 3321 1.1 mrg bra 1f 3322 1.1 mrg Lmulsf$a$0: 3323 1.1 mrg movel a6@(12),d1 | get b again to check for non-finiteness 3324 1.1 mrg 1: bclr IMM (31),d1 | clear sign bit 3325 1.1 mrg cmpl IMM (INFINITY),d1 | and check for a large exponent 3326 1.1 mrg bge Lf$inop | if b is +/-INFINITY or NaN return NaN 3327 1.1 mrg movel d7,d0 | else return signed zero 3328 1.1 mrg PICLEA SYM (_fpCCR),a0 | 3329 1.1 mrg movew IMM (0),a0@ | 3330 1.1 mrg #ifndef __mcoldfire__ 3331 1.1 mrg moveml sp@+,d2-d7 | 3332 1.1 mrg #else 3333 1.1 mrg moveml sp@,d2-d7 3334 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3335 1.1 mrg | be adjusted here. 3336 1.1 mrg #endif 3337 1.1 mrg unlk a6 | 3338 1.1 mrg rts | 3339 1.1 mrg 3340 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 3341 1.1 mrg | hidden bit back into the fraction; instead we shift left until bit 23 3342 1.1 mrg | (the hidden bit) is set, adjusting the exponent accordingly. We do this 3343 1.1 mrg | to ensure that the product of the fractions is close to 1. 3344 1.1 mrg Lmulsf$a$den: 3345 1.1 mrg movel IMM (1),d2 3346 1.1 mrg andl d5,d0 3347 1.1 mrg 1: addl d0,d0 | shift a left (until bit 23 is set) 3348 1.1 mrg #ifndef __mcoldfire__ 3349 1.1 mrg subw IMM (1),d2 | and adjust exponent 3350 1.1 mrg #else 3351 1.1 mrg subql IMM (1),d2 | and adjust exponent 3352 1.1 mrg #endif 3353 1.1 mrg btst IMM (FLT_MANT_DIG-1),d0 3354 1.1 mrg bne Lmulsf$1 | 3355 1.1 mrg bra 1b | else loop back 3356 1.1 mrg 3357 1.1 mrg Lmulsf$b$den: 3358 1.1 mrg movel IMM (1),d3 3359 1.1 mrg andl d5,d1 3360 1.1 mrg 1: addl d1,d1 | shift b left until bit 23 is set 3361 1.1 mrg #ifndef __mcoldfire__ 3362 1.1 mrg subw IMM (1),d3 | and adjust exponent 3363 1.1 mrg #else 3364 1.1 mrg subql IMM (1),d3 | and adjust exponent 3365 1.1 mrg #endif 3366 1.1 mrg btst IMM (FLT_MANT_DIG-1),d1 3367 1.1 mrg bne Lmulsf$2 | 3368 1.1 mrg bra 1b | else loop back 3369 1.1 mrg 3370 1.1 mrg |============================================================================= 3371 1.1 mrg | __divsf3 3372 1.1 mrg |============================================================================= 3373 1.1 mrg 3374 1.1 mrg | float __divsf3(float, float); 3375 1.1 mrg FUNC(__divsf3) 3376 1.1 mrg SYM (__divsf3): 3377 1.1 mrg #ifndef __mcoldfire__ 3378 1.1 mrg link a6,IMM (0) 3379 1.1 mrg moveml d2-d7,sp@- 3380 1.1 mrg #else 3381 1.1 mrg link a6,IMM (-24) 3382 1.1 mrg moveml d2-d7,sp@ 3383 1.1 mrg #endif 3384 1.1 mrg movel a6@(8),d0 | get a into d0 3385 1.1 mrg movel a6@(12),d1 | and b into d1 3386 1.1 mrg movel d0,d7 | d7 will hold the sign of the result 3387 1.1 mrg eorl d1,d7 | 3388 1.1 mrg andl IMM (0x80000000),d7 | 3389 1.1 mrg movel IMM (INFINITY),d6 | useful constant (+INFINITY) 3390 1.1 mrg movel d6,d5 | another (mask for fraction) 3391 1.1 mrg notl d5 | 3392 1.1 mrg movel IMM (0x00800000),d4 | this is to put hidden bit back 3393 1.1 mrg bclr IMM (31),d0 | get rid of a's sign bit ' 3394 1.1 mrg movel d0,d2 | 3395 1.1 mrg beq Ldivsf$a$0 | branch if a is zero 3396 1.1 mrg bclr IMM (31),d1 | get rid of b's sign bit ' 3397 1.1 mrg movel d1,d3 | 3398 1.1 mrg beq Ldivsf$b$0 | branch if b is zero 3399 1.1 mrg cmpl d6,d0 | is a big? 3400 1.1 mrg bhi Ldivsf$inop | if a is NaN return NaN 3401 1.1 mrg beq Ldivsf$inf | if a is INFINITY we have to check b 3402 1.1 mrg cmpl d6,d1 | now compare b with INFINITY 3403 1.1 mrg bhi Ldivsf$inop | if b is NaN return NaN 3404 1.1 mrg beq Ldivsf$underflow 3405 1.1 mrg | Here we have both numbers finite and nonzero (and with no sign bit). 3406 1.1 mrg | Now we get the exponents into d2 and d3 and normalize the numbers to 3407 1.1 mrg | ensure that the ratio of the fractions is close to 1. We do this by 3408 1.1 mrg | making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set. 3409 1.1 mrg andl d6,d2 | and isolate exponent in d2 3410 1.1 mrg beq Ldivsf$a$den | if exponent is zero we have a denormalized 3411 1.1 mrg andl d5,d0 | and isolate fraction 3412 1.1 mrg orl d4,d0 | and put hidden bit back 3413 1.1 mrg swap d2 | I like exponents in the first byte 3414 1.1 mrg #ifndef __mcoldfire__ 3415 1.1 mrg lsrw IMM (7),d2 | 3416 1.1 mrg #else 3417 1.1 mrg lsrl IMM (7),d2 | 3418 1.1 mrg #endif 3419 1.1 mrg Ldivsf$1: | 3420 1.1 mrg andl d6,d3 | 3421 1.1 mrg beq Ldivsf$b$den | 3422 1.1 mrg andl d5,d1 | 3423 1.1 mrg orl d4,d1 | 3424 1.1 mrg swap d3 | 3425 1.1 mrg #ifndef __mcoldfire__ 3426 1.1 mrg lsrw IMM (7),d3 | 3427 1.1 mrg #else 3428 1.1 mrg lsrl IMM (7),d3 | 3429 1.1 mrg #endif 3430 1.1 mrg Ldivsf$2: | 3431 1.1 mrg #ifndef __mcoldfire__ 3432 1.1 mrg subw d3,d2 | subtract exponents 3433 1.1 mrg addw IMM (F_BIAS),d2 | and add bias 3434 1.1 mrg #else 3435 1.1 mrg subl d3,d2 | subtract exponents 3436 1.1 mrg addl IMM (F_BIAS),d2 | and add bias 3437 1.1 mrg #endif 3438 1.1 mrg 3439 1.1 mrg | We are now ready to do the division. We have prepared things in such a way 3440 1.1 mrg | that the ratio of the fractions will be less than 2 but greater than 1/2. 3441 1.1 mrg | At this point the registers in use are: 3442 1.1 mrg | d0 holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1) 3443 1.1 mrg | d1 holds b (second operand, bit FLT_MANT_DIG=1) 3444 1.1 mrg | d2 holds the difference of the exponents, corrected by the bias 3445 1.1 mrg | d7 holds the sign of the ratio 3446 1.1 mrg | d4, d5, d6 hold some constants 3447 1.1 mrg movel d7,a0 | d6-d7 will hold the ratio of the fractions 3448 1.1 mrg movel IMM (0),d6 | 3449 1.1 mrg movel d6,d7 3450 1.1 mrg 3451 1.1 mrg moveq IMM (FLT_MANT_DIG+1),d3 3452 1.1 mrg 1: cmpl d0,d1 | is a < b? 3453 1.1 mrg bhi 2f | 3454 1.1 mrg bset d3,d6 | set a bit in d6 3455 1.1 mrg subl d1,d0 | if a >= b a <-- a-b 3456 1.1 mrg beq 3f | if a is zero, exit 3457 1.1 mrg 2: addl d0,d0 | multiply a by 2 3458 1.1 mrg #ifndef __mcoldfire__ 3459 1.1 mrg dbra d3,1b 3460 1.1 mrg #else 3461 1.1 mrg subql IMM (1),d3 3462 1.1 mrg bpl 1b 3463 1.1 mrg #endif 3464 1.1 mrg 3465 1.1 mrg | Now we keep going to set the sticky bit ... 3466 1.1 mrg moveq IMM (FLT_MANT_DIG),d3 3467 1.1 mrg 1: cmpl d0,d1 3468 1.1 mrg ble 2f 3469 1.1 mrg addl d0,d0 3470 1.1 mrg #ifndef __mcoldfire__ 3471 1.1 mrg dbra d3,1b 3472 1.1 mrg #else 3473 1.1 mrg subql IMM(1),d3 3474 1.1 mrg bpl 1b 3475 1.1 mrg #endif 3476 1.1 mrg movel IMM (0),d1 3477 1.1 mrg bra 3f 3478 1.1 mrg 2: movel IMM (0),d1 3479 1.1 mrg #ifndef __mcoldfire__ 3480 1.1 mrg subw IMM (FLT_MANT_DIG),d3 3481 1.1 mrg addw IMM (31),d3 3482 1.1 mrg #else 3483 1.1 mrg subl IMM (FLT_MANT_DIG),d3 3484 1.1 mrg addl IMM (31),d3 3485 1.1 mrg #endif 3486 1.1 mrg bset d3,d1 3487 1.1 mrg 3: 3488 1.1 mrg movel d6,d0 | put the ratio in d0-d1 3489 1.1 mrg movel a0,d7 | get sign back 3490 1.1 mrg 3491 1.1 mrg | Because of the normalization we did before we are guaranteed that 3492 1.1 mrg | d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set, 3493 1.1 mrg | bit 25 could be set, and if it is not set then bit 24 is necessarily set. 3494 1.1 mrg btst IMM (FLT_MANT_DIG+1),d0 3495 1.1 mrg beq 1f | if it is not set, then bit 24 is set 3496 1.1 mrg lsrl IMM (1),d0 | 3497 1.1 mrg #ifndef __mcoldfire__ 3498 1.1 mrg addw IMM (1),d2 | 3499 1.1 mrg #else 3500 1.1 mrg addl IMM (1),d2 | 3501 1.1 mrg #endif 3502 1.1 mrg 1: 3503 1.1 mrg | Now round, check for over- and underflow, and exit. 3504 1.1 mrg moveq IMM (DIVIDE),d5 3505 1.1 mrg bra Lround$exit 3506 1.1 mrg 3507 1.1 mrg Ldivsf$inop: 3508 1.1 mrg moveq IMM (DIVIDE),d5 3509 1.1 mrg bra Lf$inop 3510 1.1 mrg 3511 1.1 mrg Ldivsf$overflow: 3512 1.1 mrg moveq IMM (DIVIDE),d5 3513 1.1 mrg bra Lf$overflow 3514 1.1 mrg 3515 1.1 mrg Ldivsf$underflow: 3516 1.1 mrg moveq IMM (DIVIDE),d5 3517 1.1 mrg bra Lf$underflow 3518 1.1 mrg 3519 1.1 mrg Ldivsf$a$0: 3520 1.1 mrg moveq IMM (DIVIDE),d5 3521 1.1 mrg | If a is zero check to see whether b is zero also. In that case return 3522 1.1 mrg | NaN; then check if b is NaN, and return NaN also in that case. Else 3523 1.1 mrg | return a properly signed zero. 3524 1.1 mrg andl IMM (0x7fffffff),d1 | clear sign bit and test b 3525 1.1 mrg beq Lf$inop | if b is also zero return NaN 3526 1.1 mrg cmpl IMM (INFINITY),d1 | check for NaN 3527 1.1 mrg bhi Lf$inop | 3528 1.1 mrg movel d7,d0 | else return signed zero 3529 1.1 mrg PICLEA SYM (_fpCCR),a0 | 3530 1.1 mrg movew IMM (0),a0@ | 3531 1.1 mrg #ifndef __mcoldfire__ 3532 1.1 mrg moveml sp@+,d2-d7 | 3533 1.1 mrg #else 3534 1.1 mrg moveml sp@,d2-d7 | 3535 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3536 1.1 mrg | be adjusted here. 3537 1.1 mrg #endif 3538 1.1 mrg unlk a6 | 3539 1.1 mrg rts | 3540 1.1 mrg 3541 1.1 mrg Ldivsf$b$0: 3542 1.1 mrg moveq IMM (DIVIDE),d5 3543 1.1 mrg | If we got here a is not zero. Check if a is NaN; in that case return NaN, 3544 1.1 mrg | else return +/-INFINITY. Remember that a is in d0 with the sign bit 3545 1.1 mrg | cleared already. 3546 1.1 mrg cmpl IMM (INFINITY),d0 | compare d0 with INFINITY 3547 1.1 mrg bhi Lf$inop | if larger it is NaN 3548 1.1 mrg bra Lf$div$0 | else signal DIVIDE_BY_ZERO 3549 1.1 mrg 3550 1.1 mrg Ldivsf$inf: 3551 1.1 mrg moveq IMM (DIVIDE),d5 3552 1.1 mrg | If a is INFINITY we have to check b 3553 1.1 mrg cmpl IMM (INFINITY),d1 | compare b with INFINITY 3554 1.1 mrg bge Lf$inop | if b is NaN or INFINITY return NaN 3555 1.1 mrg bra Lf$overflow | else return overflow 3556 1.1 mrg 3557 1.1 mrg | If a number is denormalized we put an exponent of 1 but do not put the 3558 1.1 mrg | bit back into the fraction. 3559 1.1 mrg Ldivsf$a$den: 3560 1.1 mrg movel IMM (1),d2 3561 1.1 mrg andl d5,d0 3562 1.1 mrg 1: addl d0,d0 | shift a left until bit FLT_MANT_DIG-1 is set 3563 1.1 mrg #ifndef __mcoldfire__ 3564 1.1 mrg subw IMM (1),d2 | and adjust exponent 3565 1.1 mrg #else 3566 1.1 mrg subl IMM (1),d2 | and adjust exponent 3567 1.1 mrg #endif 3568 1.1 mrg btst IMM (FLT_MANT_DIG-1),d0 3569 1.1 mrg bne Ldivsf$1 3570 1.1 mrg bra 1b 3571 1.1 mrg 3572 1.1 mrg Ldivsf$b$den: 3573 1.1 mrg movel IMM (1),d3 3574 1.1 mrg andl d5,d1 3575 1.1 mrg 1: addl d1,d1 | shift b left until bit FLT_MANT_DIG is set 3576 1.1 mrg #ifndef __mcoldfire__ 3577 1.1 mrg subw IMM (1),d3 | and adjust exponent 3578 1.1 mrg #else 3579 1.1 mrg subl IMM (1),d3 | and adjust exponent 3580 1.1 mrg #endif 3581 1.1 mrg btst IMM (FLT_MANT_DIG-1),d1 3582 1.1 mrg bne Ldivsf$2 3583 1.1 mrg bra 1b 3584 1.1 mrg 3585 1.1 mrg Lround$exit: 3586 1.1 mrg | This is a common exit point for __mulsf3 and __divsf3. 3587 1.1 mrg 3588 1.1 mrg | First check for underlow in the exponent: 3589 1.1 mrg #ifndef __mcoldfire__ 3590 1.1 mrg cmpw IMM (-FLT_MANT_DIG-1),d2 3591 1.1 mrg #else 3592 1.1 mrg cmpl IMM (-FLT_MANT_DIG-1),d2 3593 1.1 mrg #endif 3594 1.1 mrg blt Lf$underflow 3595 1.1 mrg | It could happen that the exponent is less than 1, in which case the 3596 1.1 mrg | number is denormalized. In this case we shift right and adjust the 3597 1.1 mrg | exponent until it becomes 1 or the fraction is zero (in the latter case 3598 1.1 mrg | we signal underflow and return zero). 3599 1.1 mrg movel IMM (0),d6 | d6 is used temporarily 3600 1.1 mrg #ifndef __mcoldfire__ 3601 1.1 mrg cmpw IMM (1),d2 | if the exponent is less than 1 we 3602 1.1 mrg #else 3603 1.1 mrg cmpl IMM (1),d2 | if the exponent is less than 1 we 3604 1.1 mrg #endif 3605 1.1 mrg bge 2f | have to shift right (denormalize) 3606 1.1 mrg 1: 3607 1.1 mrg #ifndef __mcoldfire__ 3608 1.1 mrg addw IMM (1),d2 | adjust the exponent 3609 1.1 mrg lsrl IMM (1),d0 | shift right once 3610 1.1 mrg roxrl IMM (1),d1 | 3611 1.1 mrg roxrl IMM (1),d6 | d6 collect bits we would lose otherwise 3612 1.1 mrg cmpw IMM (1),d2 | is the exponent 1 already? 3613 1.1 mrg #else 3614 1.1 mrg addql IMM (1),d2 | adjust the exponent 3615 1.1 mrg lsrl IMM (1),d6 3616 1.1 mrg btst IMM (0),d1 3617 1.1 mrg beq 11f 3618 1.1 mrg bset IMM (31),d6 3619 1.1 mrg 11: lsrl IMM (1),d1 3620 1.1 mrg btst IMM (0),d0 3621 1.1 mrg beq 10f 3622 1.1 mrg bset IMM (31),d1 3623 1.1 mrg 10: lsrl IMM (1),d0 3624 1.1 mrg cmpl IMM (1),d2 | is the exponent 1 already? 3625 1.1 mrg #endif 3626 1.1 mrg beq 2f | if not loop back 3627 1.1 mrg bra 1b | 3628 1.1 mrg bra Lf$underflow | safety check, shouldn't execute ' 3629 1.1 mrg 2: orl d6,d1 | this is a trick so we don't lose ' 3630 1.1 mrg | the extra bits which were flushed right 3631 1.1 mrg | Now call the rounding routine (which takes care of denormalized numbers): 3632 1.1 mrg lea pc@(Lround$0),a0 | to return from rounding routine 3633 1.1 mrg PICLEA SYM (_fpCCR),a1 | check the rounding mode 3634 1.1 mrg #ifdef __mcoldfire__ 3635 1.1 mrg clrl d6 3636 1.1 mrg #endif 3637 1.1 mrg movew a1@(6),d6 | rounding mode in d6 3638 1.1 mrg beq Lround$to$nearest 3639 1.1 mrg #ifndef __mcoldfire__ 3640 1.1 mrg cmpw IMM (ROUND_TO_PLUS),d6 3641 1.1 mrg #else 3642 1.1 mrg cmpl IMM (ROUND_TO_PLUS),d6 3643 1.1 mrg #endif 3644 1.1 mrg bhi Lround$to$minus 3645 1.1 mrg blt Lround$to$zero 3646 1.1 mrg bra Lround$to$plus 3647 1.1 mrg Lround$0: 3648 1.1 mrg | Here we have a correctly rounded result (either normalized or denormalized). 3649 1.1 mrg 3650 1.1 mrg | Here we should have either a normalized number or a denormalized one, and 3651 1.1 mrg | the exponent is necessarily larger or equal to 1 (so we don't have to ' 3652 1.1 mrg | check again for underflow!). We have to check for overflow or for a 3653 1.1 mrg | denormalized number (which also signals underflow). 3654 1.1 mrg | Check for overflow (i.e., exponent >= 255). 3655 1.1 mrg #ifndef __mcoldfire__ 3656 1.1 mrg cmpw IMM (0x00ff),d2 3657 1.1 mrg #else 3658 1.1 mrg cmpl IMM (0x00ff),d2 3659 1.1 mrg #endif 3660 1.1 mrg bge Lf$overflow 3661 1.1 mrg | Now check for a denormalized number (exponent==0). 3662 1.1 mrg movew d2,d2 3663 1.1 mrg beq Lf$den 3664 1.1 mrg 1: 3665 1.1 mrg | Put back the exponents and sign and return. 3666 1.1 mrg #ifndef __mcoldfire__ 3667 1.1 mrg lslw IMM (7),d2 | exponent back to fourth byte 3668 1.1 mrg #else 3669 1.1 mrg lsll IMM (7),d2 | exponent back to fourth byte 3670 1.1 mrg #endif 3671 1.1 mrg bclr IMM (FLT_MANT_DIG-1),d0 3672 1.1 mrg swap d0 | and put back exponent 3673 1.1 mrg #ifndef __mcoldfire__ 3674 1.1 mrg orw d2,d0 | 3675 1.1 mrg #else 3676 1.1 mrg orl d2,d0 3677 1.1 mrg #endif 3678 1.1 mrg swap d0 | 3679 1.1 mrg orl d7,d0 | and sign also 3680 1.1 mrg 3681 1.1 mrg PICLEA SYM (_fpCCR),a0 3682 1.1 mrg movew IMM (0),a0@ 3683 1.1 mrg #ifndef __mcoldfire__ 3684 1.1 mrg moveml sp@+,d2-d7 3685 1.1 mrg #else 3686 1.1 mrg moveml sp@,d2-d7 3687 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3688 1.1 mrg | be adjusted here. 3689 1.1 mrg #endif 3690 1.1 mrg unlk a6 3691 1.1 mrg rts 3692 1.1 mrg 3693 1.1 mrg |============================================================================= 3694 1.1 mrg | __negsf2 3695 1.1 mrg |============================================================================= 3696 1.1 mrg 3697 1.1 mrg | This is trivial and could be shorter if we didn't bother checking for NaN ' 3698 1.1 mrg | and +/-INFINITY. 3699 1.1 mrg 3700 1.1 mrg | float __negsf2(float); 3701 1.1 mrg FUNC(__negsf2) 3702 1.1 mrg SYM (__negsf2): 3703 1.1 mrg #ifndef __mcoldfire__ 3704 1.1 mrg link a6,IMM (0) 3705 1.1 mrg moveml d2-d7,sp@- 3706 1.1 mrg #else 3707 1.1 mrg link a6,IMM (-24) 3708 1.1 mrg moveml d2-d7,sp@ 3709 1.1 mrg #endif 3710 1.1 mrg moveq IMM (NEGATE),d5 3711 1.1 mrg movel a6@(8),d0 | get number to negate in d0 3712 1.1 mrg bchg IMM (31),d0 | negate 3713 1.1 mrg movel d0,d1 | make a positive copy 3714 1.1 mrg bclr IMM (31),d1 | 3715 1.1 mrg tstl d1 | check for zero 3716 1.1 mrg beq 2f | if zero (either sign) return +zero 3717 1.1 mrg cmpl IMM (INFINITY),d1 | compare to +INFINITY 3718 1.1 mrg blt 1f | 3719 1.1 mrg bhi Lf$inop | if larger (fraction not zero) is NaN 3720 1.1 mrg movel d0,d7 | else get sign and return INFINITY 3721 1.1 mrg andl IMM (0x80000000),d7 3722 1.1 mrg bra Lf$infty 3723 1.1 mrg 1: PICLEA SYM (_fpCCR),a0 3724 1.1 mrg movew IMM (0),a0@ 3725 1.1 mrg #ifndef __mcoldfire__ 3726 1.1 mrg moveml sp@+,d2-d7 3727 1.1 mrg #else 3728 1.1 mrg moveml sp@,d2-d7 3729 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3730 1.1 mrg | be adjusted here. 3731 1.1 mrg #endif 3732 1.1 mrg unlk a6 3733 1.1 mrg rts 3734 1.1 mrg 2: bclr IMM (31),d0 3735 1.1 mrg bra 1b 3736 1.1 mrg 3737 1.1 mrg |============================================================================= 3738 1.1 mrg | __cmpsf2 3739 1.1 mrg |============================================================================= 3740 1.1 mrg 3741 1.1 mrg GREATER = 1 3742 1.1 mrg LESS = -1 3743 1.1 mrg EQUAL = 0 3744 1.1 mrg 3745 1.1 mrg | int __cmpsf2_internal(float, float, int); 3746 1.1 mrg SYM (__cmpsf2_internal): 3747 1.1 mrg #ifndef __mcoldfire__ 3748 1.1 mrg link a6,IMM (0) 3749 1.1 mrg moveml d2-d7,sp@- | save registers 3750 1.1 mrg #else 3751 1.1 mrg link a6,IMM (-24) 3752 1.1 mrg moveml d2-d7,sp@ 3753 1.1 mrg #endif 3754 1.1 mrg moveq IMM (COMPARE),d5 3755 1.1 mrg movel a6@(8),d0 | get first operand 3756 1.1 mrg movel a6@(12),d1 | get second operand 3757 1.1 mrg | Check if either is NaN, and in that case return garbage and signal 3758 1.1 mrg | INVALID_OPERATION. Check also if either is zero, and clear the signs 3759 1.1 mrg | if necessary. 3760 1.1 mrg movel d0,d6 3761 1.1 mrg andl IMM (0x7fffffff),d0 3762 1.1 mrg beq Lcmpsf$a$0 3763 1.1 mrg cmpl IMM (0x7f800000),d0 3764 1.1 mrg bhi Lcmpf$inop 3765 1.1 mrg Lcmpsf$1: 3766 1.1 mrg movel d1,d7 3767 1.1 mrg andl IMM (0x7fffffff),d1 3768 1.1 mrg beq Lcmpsf$b$0 3769 1.1 mrg cmpl IMM (0x7f800000),d1 3770 1.1 mrg bhi Lcmpf$inop 3771 1.1 mrg Lcmpsf$2: 3772 1.1 mrg | Check the signs 3773 1.1 mrg eorl d6,d7 3774 1.1 mrg bpl 1f 3775 1.1 mrg | If the signs are not equal check if a >= 0 3776 1.1 mrg tstl d6 3777 1.1 mrg bpl Lcmpsf$a$gt$b | if (a >= 0 && b < 0) => a > b 3778 1.1 mrg bmi Lcmpsf$b$gt$a | if (a < 0 && b >= 0) => a < b 3779 1.1 mrg 1: 3780 1.1 mrg | If the signs are equal check for < 0 3781 1.1 mrg tstl d6 3782 1.1 mrg bpl 1f 3783 1.1 mrg | If both are negative exchange them 3784 1.1 mrg #ifndef __mcoldfire__ 3785 1.1 mrg exg d0,d1 3786 1.1 mrg #else 3787 1.1 mrg movel d0,d7 3788 1.1 mrg movel d1,d0 3789 1.1 mrg movel d7,d1 3790 1.1 mrg #endif 3791 1.1 mrg 1: 3792 1.1 mrg | Now that they are positive we just compare them as longs (does this also 3793 1.1 mrg | work for denormalized numbers?). 3794 1.1 mrg cmpl d0,d1 3795 1.1 mrg bhi Lcmpsf$b$gt$a | |b| > |a| 3796 1.1 mrg bne Lcmpsf$a$gt$b | |b| < |a| 3797 1.1 mrg | If we got here a == b. 3798 1.1 mrg movel IMM (EQUAL),d0 3799 1.1 mrg #ifndef __mcoldfire__ 3800 1.1 mrg moveml sp@+,d2-d7 | put back the registers 3801 1.1 mrg #else 3802 1.1 mrg moveml sp@,d2-d7 3803 1.1 mrg #endif 3804 1.1 mrg unlk a6 3805 1.1 mrg rts 3806 1.1 mrg Lcmpsf$a$gt$b: 3807 1.1 mrg movel IMM (GREATER),d0 3808 1.1 mrg #ifndef __mcoldfire__ 3809 1.1 mrg moveml sp@+,d2-d7 | put back the registers 3810 1.1 mrg #else 3811 1.1 mrg moveml sp@,d2-d7 3812 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3813 1.1 mrg | be adjusted here. 3814 1.1 mrg #endif 3815 1.1 mrg unlk a6 3816 1.1 mrg rts 3817 1.1 mrg Lcmpsf$b$gt$a: 3818 1.1 mrg movel IMM (LESS),d0 3819 1.1 mrg #ifndef __mcoldfire__ 3820 1.1 mrg moveml sp@+,d2-d7 | put back the registers 3821 1.1 mrg #else 3822 1.1 mrg moveml sp@,d2-d7 3823 1.1 mrg | XXX if frame pointer is ever removed, stack pointer must 3824 1.1 mrg | be adjusted here. 3825 1.1 mrg #endif 3826 1.1 mrg unlk a6 3827 1.1 mrg rts 3828 1.1 mrg 3829 1.1 mrg Lcmpsf$a$0: 3830 1.1 mrg bclr IMM (31),d6 3831 1.1 mrg bra Lcmpsf$1 3832 1.1 mrg Lcmpsf$b$0: 3833 1.1 mrg bclr IMM (31),d7 3834 1.1 mrg bra Lcmpsf$2 3835 1.1 mrg 3836 1.1 mrg Lcmpf$inop: 3837 1.1 mrg movl a6@(16),d0 3838 1.1 mrg moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7 3839 1.1 mrg moveq IMM (SINGLE_FLOAT),d6 3840 1.1 mrg PICJUMP $_exception_handler 3841 1.1 mrg 3842 1.1 mrg | int __cmpsf2(float, float); 3843 1.1 mrg FUNC(__cmpsf2) 3844 1.1 mrg SYM (__cmpsf2): 3845 1.1 mrg link a6,IMM (0) 3846 1.1 mrg pea 1 3847 1.1 mrg movl a6@(12),sp@- 3848 1.1 mrg movl a6@(8),sp@- 3849 1.1 mrg PICCALL SYM (__cmpsf2_internal) 3850 1.1 mrg unlk a6 3851 1.1 mrg rts 3852 1.1 mrg 3853 1.1 mrg |============================================================================= 3854 1.1 mrg | rounding routines 3855 1.1 mrg |============================================================================= 3856 1.1 mrg 3857 1.1 mrg | The rounding routines expect the number to be normalized in registers 3858 1.1 mrg | d0-d1, with the exponent in register d2. They assume that the 3859 1.1 mrg | exponent is larger or equal to 1. They return a properly normalized number 3860 1.1 mrg | if possible, and a denormalized number otherwise. The exponent is returned 3861 1.1 mrg | in d2. 3862 1.1 mrg 3863 1.1 mrg Lround$to$nearest: 3864 1.1 mrg | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"): 3865 1.1 mrg | Here we assume that the exponent is not too small (this should be checked 3866 1.1 mrg | before entering the rounding routine), but the number could be denormalized. 3867 1.1 mrg 3868 1.1 mrg | Check for denormalized numbers: 3869 1.1 mrg 1: btst IMM (FLT_MANT_DIG),d0 3870 1.1 mrg bne 2f | if set the number is normalized 3871 1.1 mrg | Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent 3872 1.1 mrg | is one (remember that a denormalized number corresponds to an 3873 1.1 mrg | exponent of -F_BIAS+1). 3874 1.1 mrg #ifndef __mcoldfire__ 3875 1.1 mrg cmpw IMM (1),d2 | remember that the exponent is at least one 3876 1.1 mrg #else 3877 1.1 mrg cmpl IMM (1),d2 | remember that the exponent is at least one 3878 1.1 mrg #endif 3879 1.1 mrg beq 2f | an exponent of one means denormalized 3880 1.1 mrg addl d1,d1 | else shift and adjust the exponent 3881 1.1 mrg addxl d0,d0 | 3882 1.1 mrg #ifndef __mcoldfire__ 3883 1.1 mrg dbra d2,1b | 3884 1.1 mrg #else 3885 1.1 mrg subql IMM (1),d2 3886 1.1 mrg bpl 1b 3887 1.1 mrg #endif 3888 1.1 mrg 2: 3889 1.1 mrg | Now round: we do it as follows: after the shifting we can write the 3890 1.1 mrg | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2. 3891 1.1 mrg | If delta < 1, do nothing. If delta > 1, add 1 to f. 3892 1.1 mrg | If delta == 1, we make sure the rounded number will be even (odd?) 3893 1.1 mrg | (after shifting). 3894 1.1 mrg btst IMM (0),d0 | is delta < 1? 3895 1.1 mrg beq 2f | if so, do not do anything 3896 1.1 mrg tstl d1 | is delta == 1? 3897 1.1 mrg bne 1f | if so round to even 3898 1.1 mrg movel d0,d1 | 3899 1.1 mrg andl IMM (2),d1 | bit 1 is the last significant bit 3900 1.1 mrg addl d1,d0 | 3901 1.1 mrg bra 2f | 3902 1.1 mrg 1: movel IMM (1),d1 | else add 1 3903 1.1 mrg addl d1,d0 | 3904 1.1 mrg | Shift right once (because we used bit #FLT_MANT_DIG!). 3905 1.1 mrg 2: lsrl IMM (1),d0 3906 1.1 mrg | Now check again bit #FLT_MANT_DIG (rounding could have produced a 3907 1.1 mrg | 'fraction overflow' ...). 3908 1.1 mrg btst IMM (FLT_MANT_DIG),d0 3909 1.1 mrg beq 1f 3910 1.1 mrg lsrl IMM (1),d0 3911 1.1 mrg #ifndef __mcoldfire__ 3912 1.1 mrg addw IMM (1),d2 3913 1.1 mrg #else 3914 1.1 mrg addql IMM (1),d2 3915 1.1 mrg #endif 3916 1.1 mrg 1: 3917 1.1 mrg | If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we 3918 1.1 mrg | have to put the exponent to zero and return a denormalized number. 3919 1.1 mrg btst IMM (FLT_MANT_DIG-1),d0 3920 1.1 mrg beq 1f 3921 1.1 mrg jmp a0@ 3922 1.1 mrg 1: movel IMM (0),d2 3923 1.1 mrg jmp a0@ 3924 1.1 mrg 3925 1.1 mrg Lround$to$zero: 3926 1.1 mrg Lround$to$plus: 3927 1.1 mrg Lround$to$minus: 3928 1.1 mrg jmp a0@ 3929 1.1 mrg #endif /* L_float */ 3930 1.1 mrg 3931 1.1 mrg | gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2, 3932 1.1 mrg | __ledf2, __ltdf2 to all return the same value as a direct call to 3933 1.1 mrg | __cmpdf2 would. In this implementation, each of these routines 3934 1.1 mrg | simply calls __cmpdf2. It would be more efficient to give the 3935 1.1 mrg | __cmpdf2 routine several names, but separating them out will make it 3936 1.1 mrg | easier to write efficient versions of these routines someday. 3937 1.1 mrg | If the operands recompare unordered unordered __gtdf2 and __gedf2 return -1. 3938 1.1 mrg | The other routines return 1. 3939 1.1 mrg 3940 1.1 mrg #ifdef L_eqdf2 3941 1.1 mrg .text 3942 1.1 mrg FUNC(__eqdf2) 3943 1.1 mrg .globl SYM (__eqdf2) 3944 1.1 mrg SYM (__eqdf2): 3945 1.1 mrg link a6,IMM (0) 3946 1.1 mrg pea 1 3947 1.1 mrg movl a6@(20),sp@- 3948 1.1 mrg movl a6@(16),sp@- 3949 1.1 mrg movl a6@(12),sp@- 3950 1.1 mrg movl a6@(8),sp@- 3951 1.1 mrg PICCALL SYM (__cmpdf2_internal) 3952 1.1 mrg unlk a6 3953 1.1 mrg rts 3954 1.1 mrg #endif /* L_eqdf2 */ 3955 1.1 mrg 3956 1.1 mrg #ifdef L_nedf2 3957 1.1 mrg .text 3958 1.1 mrg FUNC(__nedf2) 3959 1.1 mrg .globl SYM (__nedf2) 3960 1.1 mrg SYM (__nedf2): 3961 1.1 mrg link a6,IMM (0) 3962 1.1 mrg pea 1 3963 1.1 mrg movl a6@(20),sp@- 3964 1.1 mrg movl a6@(16),sp@- 3965 1.1 mrg movl a6@(12),sp@- 3966 1.1 mrg movl a6@(8),sp@- 3967 1.1 mrg PICCALL SYM (__cmpdf2_internal) 3968 1.1 mrg unlk a6 3969 1.1 mrg rts 3970 1.1 mrg #endif /* L_nedf2 */ 3971 1.1 mrg 3972 1.1 mrg #ifdef L_gtdf2 3973 1.1 mrg .text 3974 1.1 mrg FUNC(__gtdf2) 3975 1.1 mrg .globl SYM (__gtdf2) 3976 1.1 mrg SYM (__gtdf2): 3977 1.1 mrg link a6,IMM (0) 3978 1.1 mrg pea -1 3979 1.1 mrg movl a6@(20),sp@- 3980 1.1 mrg movl a6@(16),sp@- 3981 1.1 mrg movl a6@(12),sp@- 3982 1.1 mrg movl a6@(8),sp@- 3983 1.1 mrg PICCALL SYM (__cmpdf2_internal) 3984 1.1 mrg unlk a6 3985 1.1 mrg rts 3986 1.1 mrg #endif /* L_gtdf2 */ 3987 1.1 mrg 3988 1.1 mrg #ifdef L_gedf2 3989 1.1 mrg .text 3990 1.1 mrg FUNC(__gedf2) 3991 1.1 mrg .globl SYM (__gedf2) 3992 1.1 mrg SYM (__gedf2): 3993 1.1 mrg link a6,IMM (0) 3994 1.1 mrg pea -1 3995 1.1 mrg movl a6@(20),sp@- 3996 1.1 mrg movl a6@(16),sp@- 3997 1.1 mrg movl a6@(12),sp@- 3998 1.1 mrg movl a6@(8),sp@- 3999 1.1 mrg PICCALL SYM (__cmpdf2_internal) 4000 1.1 mrg unlk a6 4001 1.1 mrg rts 4002 1.1 mrg #endif /* L_gedf2 */ 4003 1.1 mrg 4004 1.1 mrg #ifdef L_ltdf2 4005 1.1 mrg .text 4006 1.1 mrg FUNC(__ltdf2) 4007 1.1 mrg .globl SYM (__ltdf2) 4008 1.1 mrg SYM (__ltdf2): 4009 1.1 mrg link a6,IMM (0) 4010 1.1 mrg pea 1 4011 1.1 mrg movl a6@(20),sp@- 4012 1.1 mrg movl a6@(16),sp@- 4013 1.1 mrg movl a6@(12),sp@- 4014 1.1 mrg movl a6@(8),sp@- 4015 1.1 mrg PICCALL SYM (__cmpdf2_internal) 4016 1.1 mrg unlk a6 4017 1.1 mrg rts 4018 1.1 mrg #endif /* L_ltdf2 */ 4019 1.1 mrg 4020 1.1 mrg #ifdef L_ledf2 4021 1.1 mrg .text 4022 1.1 mrg FUNC(__ledf2) 4023 1.1 mrg .globl SYM (__ledf2) 4024 1.1 mrg SYM (__ledf2): 4025 1.1 mrg link a6,IMM (0) 4026 1.1 mrg pea 1 4027 1.1 mrg movl a6@(20),sp@- 4028 1.1 mrg movl a6@(16),sp@- 4029 1.1 mrg movl a6@(12),sp@- 4030 1.1 mrg movl a6@(8),sp@- 4031 1.1 mrg PICCALL SYM (__cmpdf2_internal) 4032 1.1 mrg unlk a6 4033 1.1 mrg rts 4034 1.1 mrg #endif /* L_ledf2 */ 4035 1.1 mrg 4036 1.1 mrg | The comments above about __eqdf2, et. al., also apply to __eqsf2, 4037 1.1 mrg | et. al., except that the latter call __cmpsf2 rather than __cmpdf2. 4038 1.1 mrg 4039 1.1 mrg #ifdef L_eqsf2 4040 1.1 mrg .text 4041 1.1 mrg FUNC(__eqsf2) 4042 1.1 mrg .globl SYM (__eqsf2) 4043 1.1 mrg SYM (__eqsf2): 4044 1.1 mrg link a6,IMM (0) 4045 1.1 mrg pea 1 4046 1.1 mrg movl a6@(12),sp@- 4047 1.1 mrg movl a6@(8),sp@- 4048 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4049 1.1 mrg unlk a6 4050 1.1 mrg rts 4051 1.1 mrg #endif /* L_eqsf2 */ 4052 1.1 mrg 4053 1.1 mrg #ifdef L_nesf2 4054 1.1 mrg .text 4055 1.1 mrg FUNC(__nesf2) 4056 1.1 mrg .globl SYM (__nesf2) 4057 1.1 mrg SYM (__nesf2): 4058 1.1 mrg link a6,IMM (0) 4059 1.1 mrg pea 1 4060 1.1 mrg movl a6@(12),sp@- 4061 1.1 mrg movl a6@(8),sp@- 4062 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4063 1.1 mrg unlk a6 4064 1.1 mrg rts 4065 1.1 mrg #endif /* L_nesf2 */ 4066 1.1 mrg 4067 1.1 mrg #ifdef L_gtsf2 4068 1.1 mrg .text 4069 1.1 mrg FUNC(__gtsf2) 4070 1.1 mrg .globl SYM (__gtsf2) 4071 1.1 mrg SYM (__gtsf2): 4072 1.1 mrg link a6,IMM (0) 4073 1.1 mrg pea -1 4074 1.1 mrg movl a6@(12),sp@- 4075 1.1 mrg movl a6@(8),sp@- 4076 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4077 1.1 mrg unlk a6 4078 1.1 mrg rts 4079 1.1 mrg #endif /* L_gtsf2 */ 4080 1.1 mrg 4081 1.1 mrg #ifdef L_gesf2 4082 1.1 mrg .text 4083 1.1 mrg FUNC(__gesf2) 4084 1.1 mrg .globl SYM (__gesf2) 4085 1.1 mrg SYM (__gesf2): 4086 1.1 mrg link a6,IMM (0) 4087 1.1 mrg pea -1 4088 1.1 mrg movl a6@(12),sp@- 4089 1.1 mrg movl a6@(8),sp@- 4090 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4091 1.1 mrg unlk a6 4092 1.1 mrg rts 4093 1.1 mrg #endif /* L_gesf2 */ 4094 1.1 mrg 4095 1.1 mrg #ifdef L_ltsf2 4096 1.1 mrg .text 4097 1.1 mrg FUNC(__ltsf2) 4098 1.1 mrg .globl SYM (__ltsf2) 4099 1.1 mrg SYM (__ltsf2): 4100 1.1 mrg link a6,IMM (0) 4101 1.1 mrg pea 1 4102 1.1 mrg movl a6@(12),sp@- 4103 1.1 mrg movl a6@(8),sp@- 4104 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4105 1.1 mrg unlk a6 4106 1.1 mrg rts 4107 1.1 mrg #endif /* L_ltsf2 */ 4108 1.1 mrg 4109 1.1 mrg #ifdef L_lesf2 4110 1.1 mrg .text 4111 1.1 mrg FUNC(__lesf2) 4112 1.1 mrg .globl SYM (__lesf2) 4113 1.1 mrg SYM (__lesf2): 4114 1.1 mrg link a6,IMM (0) 4115 1.1 mrg pea 1 4116 1.1 mrg movl a6@(12),sp@- 4117 1.1 mrg movl a6@(8),sp@- 4118 1.1 mrg PICCALL SYM (__cmpsf2_internal) 4119 1.1 mrg unlk a6 4120 1.1 mrg rts 4121 1.1 mrg #endif /* L_lesf2 */ 4122 1.1 mrg 4123 1.1 mrg #if defined (__ELF__) && defined (__linux__) 4124 1.1 mrg /* Make stack non-executable for ELF linux targets. */ 4125 1.1 mrg .section .note.GNU-stack,"",@progbits 4126 1.1 mrg #endif 4127