hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
|    x_store.sa 3.2 1/24/91
|
|    store --- store operand to memory or register
|
|    Used by underflow and overflow handlers.
|
|    a6 = points to fp value to be stored.
|
 
|        Copyright (C) Motorola, Inc. 1990
|            All Rights Reserved
|
|       For details on the license for this file, please see the
|       file, README, in this same directory.
 
X_STORE:    |idnt    2,1 | Motorola 040 Floating Point Software Package
 
   |section    8
 
fpreg_mask:
   .byte    0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
 
#include "fpsp.h"
 
   |xref    mem_write
   |xref    get_fline
   |xref    g_opcls
   |xref    g_dfmtou
   |xref    reg_dest
 
   .global    dest_ext
   .global    dest_dbl
   .global    dest_sgl
 
   .global    store
store:
   btstb    #E3,E_BYTE(%a6)
   beqs    E1_sto
E3_sto:
   movel    CMDREG3B(%a6),%d0
   bfextu    %d0{#6:#3},%d0        |isolate dest. reg from cmdreg3b
sto_fp:
   lea    fpreg_mask,%a1
   moveb    (%a1,%d0.w),%d0        |convert reg# to dynamic register mask
   tstb    LOCAL_SGN(%a0)
   beqs    is_pos
   bsetb    #sign_bit,LOCAL_EX(%a0)
is_pos:
   fmovemx (%a0),%d0        |move to correct register
|
|    if fp0-fp3 is being modified, we must put a copy
|    in the USER_FPn variable on the stack because all exception
|    handlers restore fp0-fp3 from there.
|
   cmpb    #0x80,%d0
   bnes    not_fp0
   fmovemx %fp0-%fp0,USER_FP0(%a6)
   rts
not_fp0:
   cmpb    #0x40,%d0
   bnes    not_fp1
   fmovemx %fp1-%fp1,USER_FP1(%a6)
   rts
not_fp1:
   cmpb    #0x20,%d0
   bnes    not_fp2
   fmovemx %fp2-%fp2,USER_FP2(%a6)
   rts
not_fp2:
   cmpb    #0x10,%d0
   bnes    not_fp3
   fmovemx %fp3-%fp3,USER_FP3(%a6)
   rts
not_fp3:
   rts
 
E1_sto:
   bsrl    g_opcls        |returns opclass in d0
   cmpib    #3,%d0
   beq    opc011        |branch if opclass 3
   movel    CMDREG1B(%a6),%d0
   bfextu    %d0{#6:#3},%d0    |extract destination register
   bras    sto_fp
 
opc011:
   bsrl    g_dfmtou    |returns dest format in d0
|                ;ext=00, sgl=01, dbl=10
   movel    %a0,%a1        |save source addr in a1
   movel    EXC_EA(%a6),%a0    |get the address
   cmpil    #0,%d0        |if dest format is extended
   beq    dest_ext    |then branch
   cmpil    #1,%d0        |if dest format is single
   beq    dest_sgl    |then branch
|
|    fall through to dest_dbl
|
 
|
|    dest_dbl --- write double precision value to user space
|
|Input
|    a0 -> destination address
|    a1 -> source in extended precision
|Output
|    a0 -> destroyed
|    a1 -> destroyed
|    d0 -> 0
|
|Changes extended precision to double precision.
| Note: no attempt is made to round the extended value to double.
|    dbl_sign = ext_sign
|    dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
|    get rid of ext integer bit
|    dbl_mant = ext_mant{62:12}
|
|        ---------------   ---------------    ---------------
|  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
|        ---------------   ---------------    ---------------
|         95        64    63 62          32      31     11      0
|                     |                 |
|                     |                 |
|                     |                 |
|                         v                 v
|                  ---------------   ---------------
|  double   ->              |s|exp| mant  |   |  mant       |
|                  ---------------   ---------------
|                  63     51   32   31           0
|
dest_dbl:
   clrl    %d0        |clear d0
   movew    LOCAL_EX(%a1),%d0    |get exponent
   subw    #0x3fff,%d0    |subtract extended precision bias
   cmpw    #0x4000,%d0    |check if inf
   beqs    inf        |if so, special case
   addw    #0x3ff,%d0    |add double precision bias
   swap    %d0        |d0 now in upper word
   lsll    #4,%d0        |d0 now in proper place for dbl prec exp
   tstb    LOCAL_SGN(%a1)
   beqs    get_mant    |if positive, go process mantissa
   bsetl    #31,%d0        |if negative, put in sign information
|                ; before continuing
   bras    get_mant    |go process mantissa
inf:
   movel    #0x7ff00000,%d0    |load dbl inf exponent
   clrl    LOCAL_HI(%a1)    |clear msb
   tstb    LOCAL_SGN(%a1)
   beqs    dbl_inf        |if positive, go ahead and write it
   bsetl    #31,%d0        |if negative put in sign information
dbl_inf:
   movel    %d0,LOCAL_EX(%a1)    |put the new exp back on the stack
   bras    dbl_wrt
get_mant:
   movel    LOCAL_HI(%a1),%d1    |get ms mantissa
   bfextu    %d1{#1:#20},%d1    |get upper 20 bits of ms
   orl    %d1,%d0        |put these bits in ms word of double
   movel    %d0,LOCAL_EX(%a1)    |put the new exp back on the stack
   movel    LOCAL_HI(%a1),%d1    |get ms mantissa
   movel    #21,%d0        |load shift count
   lsll    %d0,%d1        |put lower 11 bits in upper bits
   movel    %d1,LOCAL_HI(%a1)    |build lower lword in memory
   movel    LOCAL_LO(%a1),%d1    |get ls mantissa
   bfextu    %d1{#0:#21},%d0    |get ls 21 bits of double
   orl    %d0,LOCAL_HI(%a1)    |put them in double result
dbl_wrt:
   movel    #0x8,%d0        |byte count for double precision number
   exg    %a0,%a1        |a0=supervisor source, a1=user dest
   bsrl    mem_write    |move the number to the user's memory
   rts
|
|    dest_sgl --- write single precision value to user space
|
|Input
|    a0 -> destination address
|    a1 -> source in extended precision
|
|Output
|    a0 -> destroyed
|    a1 -> destroyed
|    d0 -> 0
|
|Changes extended precision to single precision.
|    sgl_sign = ext_sign
|    sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
|    get rid of ext integer bit
|    sgl_mant = ext_mant{62:12}
|
|        ---------------   ---------------    ---------------
|  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
|        ---------------   ---------------    ---------------
|         95        64    63 62       40 32      31     12      0
|                     |       |
|                     |       |
|                     |       |
|                         v     v
|                  ---------------
|  single   ->              |s|exp| mant  |
|                  ---------------
|                  31     22     0
|
dest_sgl:
   clrl    %d0
   movew    LOCAL_EX(%a1),%d0    |get exponent
   subw    #0x3fff,%d0    |subtract extended precision bias
   cmpw    #0x4000,%d0    |check if inf
   beqs    sinf        |if so, special case
   addw    #0x7f,%d0        |add single precision bias
   swap    %d0        |put exp in upper word of d0
   lsll    #7,%d0        |shift it into single exp bits
   tstb    LOCAL_SGN(%a1)
   beqs    get_sman    |if positive, continue
   bsetl    #31,%d0        |if negative, put in sign first
   bras    get_sman    |get mantissa
sinf:
   movel    #0x7f800000,%d0    |load single inf exp to d0
   tstb    LOCAL_SGN(%a1)
   beqs    sgl_wrt        |if positive, continue
   bsetl    #31,%d0        |if negative, put in sign info
   bras    sgl_wrt
 
get_sman:
   movel    LOCAL_HI(%a1),%d1    |get ms mantissa
   bfextu    %d1{#1:#23},%d1    |get upper 23 bits of ms
   orl    %d1,%d0        |put these bits in ms word of single
 
sgl_wrt:
   movel    %d0,L_SCR1(%a6)    |put the new exp back on the stack
   movel    #0x4,%d0        |byte count for single precision number
   tstl    %a0        |users destination address
   beqs    sgl_Dn        |destination is a data register
   exg    %a0,%a1        |a0=supervisor source, a1=user dest
   leal    L_SCR1(%a6),%a0    |point a0 to data
   bsrl    mem_write    |move the number to the user's memory
   rts
sgl_Dn:
   bsrl    get_fline    |returns fline word in d0
   andw    #0x7,%d0        |isolate register number
   movel    %d0,%d1        |d1 has size:reg formatted for reg_dest
   orl    #0x10,%d1        |reg_dest wants size added to reg#
   bral    reg_dest    |size is X, rts in reg_dest will
|                ;return to caller of dest_sgl
 
dest_ext:
   tstb    LOCAL_SGN(%a1)    |put back sign into exponent word
   beqs    dstx_cont
   bsetb    #sign_bit,LOCAL_EX(%a1)
dstx_cont:
   clrb    LOCAL_SGN(%a1)    |clear out the sign byte
 
   movel    #0x0c,%d0        |byte count for extended number
   exg    %a0,%a1        |a0=supervisor source, a1=user dest
   bsrl    mem_write    |move the number to the user's memory
   rts
 
   |end