1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
|
/*
* cmpsf2.s
*
* Floating point compare: r0r1 = (r0r1 > r2r3) - (r0r1 < r2r3)
* GCC apparently does not call this because it is not normal IEEE
*
* For GCC, we also implement: == != < > <= >=
* All of these return -1 0 1 as with the ordinary floating point compare
* However, all return false given NaN input, except != which returns true
*
* The non-GCC non-IEEE floating point compare returns zero given NaN input
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Librcx floating point code, released May 27, 1999.
*
* The Initial Developer of the Original Code is Kekoa Proudfoot.
* Portions created by Kekoa Proudfoot are Copyright (C) 1999
* Kekoa Proudfoot. All Rights Reserved.
*
* Contributor(s): Kekoa Proudfoot <kekoa@graphics.stanford.edu>
*/
.section .text
;;
;; functions: cmpsf2, eqsf2, nesf2, ltsf2, gtsf2, lesf2, gesf2
;; input: float in r0r1 and float at sp+2
;; output: int in r0
;;
; In all cases, assume r2 and r3 saved by caller
.global ___eqsf2
.global ___nesf2
.global ___ltsf2
.global ___lesf2
___eqsf2:
___nesf2:
___ltsf2:
___lesf2:
; Load 1 as NaN return value
mov.b #1,r2l
bra compareentry
.global ___gtsf2
.global ___gesf2
___gtsf2:
___gesf2:
; Load -1 as NaN return value
mov.b #-1,r2l
bra compareentry
.global ___cmpsf2
___cmpsf2:
; Load 0 as NaN return value
sub.b r2l,r2l
compareentry:
; Save registers
push r4
push r5
; Clear flag byte
sub.b r2h,r2h
; Set flags for first operand
mov.w r0,r3 ; copy first operand to r3r4
mov.w r1,r4
bsr setflags ; updates r2h, does not change r3r4
; Set flags for second operand
mov.w @(6,r7),r3 ; load second operand to r3r4
mov.w @(8,r7),r4
bsr setflags ; updates r2h, does not change r3r4
; Set a negative flag if both operands negative
bld #7,r0h ; load sign bit of first operand to carry
band #7,r3h ; and with sign bit of second operand
bst #2,r2h ; store carry as flag bit
; Note on flag bits: 0=either non-zero, 1=either NaN, 2=both negative
; Is the NaN flag set?
btst #1,r2h ; is NaN flag (bit 1) set?
beq endif_0 ; zero indicates false
; One of the operands is a NaN
; Move NaN return value to r0l and return
mov.b r2l,r0l
bra return
endif_0:
; Is the non-zero flag clear?
btst #0,r2h ; is non-zero flag (bit 0) clear?
bne endif_1 ; non-zero indicates false (flag set)
; Neither operand is non-zero, so both operands are zero
; Operands are equal, so move zero return value to r0l and return
sub.b r0l,r0l
bra return
endif_1:
; Subtract second operand (r3r4) from first operand (r0r1)
sub.w r4,r1
subx.b r3l,r0l
subx.b r3h,r0h
; Is the result equal to zero?
; If yes, return value of zero already in r0l, return
beq return ; zero indicates true
; Is the result greater than zero?
blt else_2
; Set the return value to 2 (for now, 2 indicates greater than)
mov.b #2,r0l
bra endif_2
else_2:
; Set return value to 0 (for now, 0 indicates less than)
sub.b r0l,r0l
endif_2:
; Is the negative flag set?
btst #2,r2h ; is negative flag (bit 2) set?
beq endif_3 ; zero indicates false
; Both operands are negative, so fix incorrect sense of compare
xor.b #2,r0l ; change 2 to 0 and 0 to 2
endif_3:
; Decrement return value
dec.b r0l ; change 2 to 1 and 0 to -1
return:
; Sign extend return value
bld #7,r0l
subx.b r0h,r0h
; Restore registers
pop r5
pop r4
; Return
rts
;;
;; function: setflags
;; input: float in r3r4, previous flags in r2h
;; output: updated flags in r2h
;; registers: assumes r5 free, preserves r3r4
;;
setflags:
; Note on relevant flag bits: 0=either non-zero, 1=either NaN
; Move upper input word to r5 and mask off msb
mov.w r3,r5
and.b #0x7f,r5h
; Is the input non-zero?
mov.w r4,r4 ; is the lower word non-zero?
bne if_4 ; non-zero indicates true
mov.w r5,r5 ; is the upper word non-zero?
beq endif_4 ; zero indicates false
if_4:
; Input is non-zero, set the non-zero flag
bset #0,r2h ; set the non-zero flag to 1
endif_4:
; Is input a NAN ((input & 7fffffff) > 7f800000) ?
add.b #0,r4l ; subtract 7f800000 from r5r4
addx.b #0,r4h ; do subtract by adding -7f800000=80800000
addx.b #0x80,r5l
addx.b #0x80,r5h
ble endif_5 ; less than or equal indicates false
; Input is NaN, set the NaN flag
bset #1,r2h
endif_5:
rts
|