File: floatsisf.s

package info (click to toggle)
brickos 0.9.0.dfsg-15
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 2,068 kB
  • sloc: ansic: 9,139; cpp: 860; asm: 693; makefile: 656; sh: 134; perl: 61
file content (180 lines) | stat: -rw-r--r-- 4,666 bytes parent folder | download | duplicates (5)
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
/*
 *  floatsisf.s
 *
 *  Signed long to floating point conversion, single precision:
 *     r0r1 = (float) long r0r1
 *  Unsigned long to floating point conversion, single precision:
 *     r0r1 = (float) unsigned long r0r1
 *
 *  GCC does not directly invoke the unsigned long conversion function
 *  Instead, it wraps the signed long function with a good amount of extra code
 *  You can save space by calling the latter conversion function yourself
 *  If you want to use it, you should invoke it yourself, as a function
 *  The declaration is: extern float __ufloatsisf (unsigned long value);
 *
 *  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>
 */

; possible optimizations
;  - integrate msb test and sticky shift with fixoverflow in joinsf
;       - add a bor #7,r5h to see if four bit is set
;  - factor out stickyshift function, rewrite fixoverflow in joinsf to call it
;       - affects this, since we can then call stickyshift right
;  - if ufloatsisf removed, msb test should set mantissa to 7fffffff
;       - also, msb test should be moved earlier to inside negative input test

    .section .text

;;
;; function: ufloatsisf
;; input: unsigned long in r0r1
;; output: float in r0r1
;;

    .global ___ufloatsisf

___ufloatsisf:

    ; Save registers (assume r2 and r3 saved by caller)

    push    r4
    push    r5
    mov.w   r6,r2               ; we need r6 specifically, but do not need r2

    ; Jump into floatsisf

    bra     ufloatentry



;;
;; function: floatsisf
;; input: signed long in r0r1
;; output: float in r0r1
;;

    .global ___floatsisf

___floatsisf:

    ; Save registers (assume r2 and r3 saved by caller)

    push    r4
    push    r5
    mov.w   r6,r2               ; we need r6 specifically, but do not need r2

    ; Is input negative?

    btst    #7,r0h              ; is r0r1 < 0?
    beq     else_0              ; equal indicates false

        ; Set sign to negative

        mov.b   #0x80,r3l       ; set sign (r3l) to 0x80 to indicate negative

        ; Store -input to mantissa

        sub.w   r5,r5           ; zero destination
        sub.w   r6,r6

        sub.w   r1,r6           ; subtract input
        subx.b  r0l,r5l
        subx.b  r0h,r5h

        bra     endif_0

    else_0:

ufloatentry:

        ; Set sign to positive

        sub.b   r3l,r3l         ; set sign (r3l) to zero to indicate positive

        ; Store input to mantissa

        mov.w   r0,r5           ; set mantissa
        mov.w   r1,r6

    endif_0:

    ; Set exponent

    mov.w   #156,r4             ; set exponent to 29 + bias, bias is 127

    ; Is msb set?

    btst    #7,r5h              ; is msb set?
    beq     else_1              ; zero indicates false

        ; Mantissa overflow, so shift right one place, maintaining sticky bit

        shlr.b  r5h             ; shift mantissa right 1 place
        rotxr.b r5l
        rotxr.b r6h
        rotxr.b r6l             ; last shift places old sticky bit in carry

        bor     #0,r6l          ; or lsb with old sticky bit
        bst     #0,r6l          ; store new sticky bit

        ; Increase exponent

        adds    #1,r4           ; add one to exponent

        bra     endif_1

    else_1:

        ; Is mantissa non-zero?

        mov.w   r5,r5           ; check upper word
        bne     if_2            ; not equal to zero indicates true
        mov.w   r6,r6           ; check lower word
        beq     endif_2         ; equal to zero indicates false

            if_2:

            ; Is the two bit (40000000) clear?

            btst    #6,r5h      ; check 40000000 bit
            bne     endif_3     ; non-zero indicates false (bit set)

                ; Normalize

                jsr  ___normalizesf

            endif_3:

        endif_2:

    endif_1:

    ; Join

    jsr  ___joinsf

return:

    ; Restore registers

    mov.w   r2,r6
    pop     r5
    pop     r4

    rts