Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | | |
2 | | x_store.sa 3.2 1/24/91 | |
3 | | | |
4 | | store --- store operand to memory or register | |
5 | | | |
6 | | Used by underflow and overflow handlers. | |
7 | | | |
8 | | a6 = points to fp value to be stored. | |
9 | | | |
10 | ||
11 | | Copyright (C) Motorola, Inc. 1990 | |
12 | | All Rights Reserved | |
13 | | | |
e00d82d0 MW |
14 | | For details on the license for this file, please see the |
15 | | file, README, in this same directory. | |
1da177e4 LT |
16 | |
17 | X_STORE: |idnt 2,1 | Motorola 040 Floating Point Software Package | |
18 | ||
19 | |section 8 | |
20 | ||
21 | fpreg_mask: | |
22 | .byte 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 | |
23 | ||
24 | #include "fpsp.h" | |
25 | ||
26 | |xref mem_write | |
27 | |xref get_fline | |
28 | |xref g_opcls | |
29 | |xref g_dfmtou | |
30 | |xref reg_dest | |
31 | ||
32 | .global dest_ext | |
33 | .global dest_dbl | |
34 | .global dest_sgl | |
35 | ||
36 | .global store | |
37 | store: | |
38 | btstb #E3,E_BYTE(%a6) | |
39 | beqs E1_sto | |
40 | E3_sto: | |
41 | movel CMDREG3B(%a6),%d0 | |
42 | bfextu %d0{#6:#3},%d0 |isolate dest. reg from cmdreg3b | |
43 | sto_fp: | |
44 | lea fpreg_mask,%a1 | |
45 | moveb (%a1,%d0.w),%d0 |convert reg# to dynamic register mask | |
46 | tstb LOCAL_SGN(%a0) | |
47 | beqs is_pos | |
48 | bsetb #sign_bit,LOCAL_EX(%a0) | |
49 | is_pos: | |
50 | fmovemx (%a0),%d0 |move to correct register | |
51 | | | |
52 | | if fp0-fp3 is being modified, we must put a copy | |
53 | | in the USER_FPn variable on the stack because all exception | |
54 | | handlers restore fp0-fp3 from there. | |
55 | | | |
56 | cmpb #0x80,%d0 | |
57 | bnes not_fp0 | |
58 | fmovemx %fp0-%fp0,USER_FP0(%a6) | |
59 | rts | |
60 | not_fp0: | |
61 | cmpb #0x40,%d0 | |
62 | bnes not_fp1 | |
63 | fmovemx %fp1-%fp1,USER_FP1(%a6) | |
64 | rts | |
65 | not_fp1: | |
66 | cmpb #0x20,%d0 | |
67 | bnes not_fp2 | |
68 | fmovemx %fp2-%fp2,USER_FP2(%a6) | |
69 | rts | |
70 | not_fp2: | |
71 | cmpb #0x10,%d0 | |
72 | bnes not_fp3 | |
73 | fmovemx %fp3-%fp3,USER_FP3(%a6) | |
74 | rts | |
75 | not_fp3: | |
76 | rts | |
77 | ||
78 | E1_sto: | |
79 | bsrl g_opcls |returns opclass in d0 | |
80 | cmpib #3,%d0 | |
81 | beq opc011 |branch if opclass 3 | |
82 | movel CMDREG1B(%a6),%d0 | |
83 | bfextu %d0{#6:#3},%d0 |extract destination register | |
84 | bras sto_fp | |
85 | ||
86 | opc011: | |
87 | bsrl g_dfmtou |returns dest format in d0 | |
88 | | ;ext=00, sgl=01, dbl=10 | |
89 | movel %a0,%a1 |save source addr in a1 | |
90 | movel EXC_EA(%a6),%a0 |get the address | |
91 | cmpil #0,%d0 |if dest format is extended | |
92 | beq dest_ext |then branch | |
93 | cmpil #1,%d0 |if dest format is single | |
94 | beq dest_sgl |then branch | |
95 | | | |
96 | | fall through to dest_dbl | |
97 | | | |
98 | ||
99 | | | |
100 | | dest_dbl --- write double precision value to user space | |
101 | | | |
102 | |Input | |
103 | | a0 -> destination address | |
104 | | a1 -> source in extended precision | |
105 | |Output | |
106 | | a0 -> destroyed | |
107 | | a1 -> destroyed | |
108 | | d0 -> 0 | |
109 | | | |
110 | |Changes extended precision to double precision. | |
111 | | Note: no attempt is made to round the extended value to double. | |
112 | | dbl_sign = ext_sign | |
113 | | dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias) | |
114 | | get rid of ext integer bit | |
115 | | dbl_mant = ext_mant{62:12} | |
116 | | | |
117 | | --------------- --------------- --------------- | |
118 | | extended -> |s| exp | |1| ms mant | | ls mant | | |
119 | | --------------- --------------- --------------- | |
120 | | 95 64 63 62 32 31 11 0 | |
121 | | | | | |
122 | | | | | |
123 | | | | | |
124 | | v v | |
125 | | --------------- --------------- | |
126 | | double -> |s|exp| mant | | mant | | |
127 | | --------------- --------------- | |
128 | | 63 51 32 31 0 | |
129 | | | |
130 | dest_dbl: | |
131 | clrl %d0 |clear d0 | |
132 | movew LOCAL_EX(%a1),%d0 |get exponent | |
133 | subw #0x3fff,%d0 |subtract extended precision bias | |
134 | cmpw #0x4000,%d0 |check if inf | |
135 | beqs inf |if so, special case | |
136 | addw #0x3ff,%d0 |add double precision bias | |
137 | swap %d0 |d0 now in upper word | |
138 | lsll #4,%d0 |d0 now in proper place for dbl prec exp | |
139 | tstb LOCAL_SGN(%a1) | |
140 | beqs get_mant |if positive, go process mantissa | |
141 | bsetl #31,%d0 |if negative, put in sign information | |
142 | | ; before continuing | |
143 | bras get_mant |go process mantissa | |
144 | inf: | |
145 | movel #0x7ff00000,%d0 |load dbl inf exponent | |
146 | clrl LOCAL_HI(%a1) |clear msb | |
147 | tstb LOCAL_SGN(%a1) | |
148 | beqs dbl_inf |if positive, go ahead and write it | |
149 | bsetl #31,%d0 |if negative put in sign information | |
150 | dbl_inf: | |
151 | movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack | |
152 | bras dbl_wrt | |
153 | get_mant: | |
154 | movel LOCAL_HI(%a1),%d1 |get ms mantissa | |
155 | bfextu %d1{#1:#20},%d1 |get upper 20 bits of ms | |
156 | orl %d1,%d0 |put these bits in ms word of double | |
157 | movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack | |
158 | movel LOCAL_HI(%a1),%d1 |get ms mantissa | |
159 | movel #21,%d0 |load shift count | |
160 | lsll %d0,%d1 |put lower 11 bits in upper bits | |
161 | movel %d1,LOCAL_HI(%a1) |build lower lword in memory | |
162 | movel LOCAL_LO(%a1),%d1 |get ls mantissa | |
163 | bfextu %d1{#0:#21},%d0 |get ls 21 bits of double | |
164 | orl %d0,LOCAL_HI(%a1) |put them in double result | |
165 | dbl_wrt: | |
166 | movel #0x8,%d0 |byte count for double precision number | |
167 | exg %a0,%a1 |a0=supervisor source, a1=user dest | |
168 | bsrl mem_write |move the number to the user's memory | |
169 | rts | |
170 | | | |
171 | | dest_sgl --- write single precision value to user space | |
172 | | | |
173 | |Input | |
174 | | a0 -> destination address | |
175 | | a1 -> source in extended precision | |
176 | | | |
177 | |Output | |
178 | | a0 -> destroyed | |
179 | | a1 -> destroyed | |
180 | | d0 -> 0 | |
181 | | | |
182 | |Changes extended precision to single precision. | |
183 | | sgl_sign = ext_sign | |
184 | | sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias) | |
185 | | get rid of ext integer bit | |
186 | | sgl_mant = ext_mant{62:12} | |
187 | | | |
188 | | --------------- --------------- --------------- | |
189 | | extended -> |s| exp | |1| ms mant | | ls mant | | |
190 | | --------------- --------------- --------------- | |
191 | | 95 64 63 62 40 32 31 12 0 | |
192 | | | | | |
193 | | | | | |
194 | | | | | |
195 | | v v | |
196 | | --------------- | |
197 | | single -> |s|exp| mant | | |
198 | | --------------- | |
199 | | 31 22 0 | |
200 | | | |
201 | dest_sgl: | |
202 | clrl %d0 | |
203 | movew LOCAL_EX(%a1),%d0 |get exponent | |
204 | subw #0x3fff,%d0 |subtract extended precision bias | |
205 | cmpw #0x4000,%d0 |check if inf | |
206 | beqs sinf |if so, special case | |
207 | addw #0x7f,%d0 |add single precision bias | |
208 | swap %d0 |put exp in upper word of d0 | |
209 | lsll #7,%d0 |shift it into single exp bits | |
210 | tstb LOCAL_SGN(%a1) | |
211 | beqs get_sman |if positive, continue | |
212 | bsetl #31,%d0 |if negative, put in sign first | |
213 | bras get_sman |get mantissa | |
214 | sinf: | |
215 | movel #0x7f800000,%d0 |load single inf exp to d0 | |
216 | tstb LOCAL_SGN(%a1) | |
217 | beqs sgl_wrt |if positive, continue | |
218 | bsetl #31,%d0 |if negative, put in sign info | |
219 | bras sgl_wrt | |
220 | ||
221 | get_sman: | |
222 | movel LOCAL_HI(%a1),%d1 |get ms mantissa | |
223 | bfextu %d1{#1:#23},%d1 |get upper 23 bits of ms | |
224 | orl %d1,%d0 |put these bits in ms word of single | |
225 | ||
226 | sgl_wrt: | |
227 | movel %d0,L_SCR1(%a6) |put the new exp back on the stack | |
228 | movel #0x4,%d0 |byte count for single precision number | |
229 | tstl %a0 |users destination address | |
230 | beqs sgl_Dn |destination is a data register | |
231 | exg %a0,%a1 |a0=supervisor source, a1=user dest | |
232 | leal L_SCR1(%a6),%a0 |point a0 to data | |
233 | bsrl mem_write |move the number to the user's memory | |
234 | rts | |
235 | sgl_Dn: | |
236 | bsrl get_fline |returns fline word in d0 | |
237 | andw #0x7,%d0 |isolate register number | |
238 | movel %d0,%d1 |d1 has size:reg formatted for reg_dest | |
239 | orl #0x10,%d1 |reg_dest wants size added to reg# | |
240 | bral reg_dest |size is X, rts in reg_dest will | |
241 | | ;return to caller of dest_sgl | |
242 | ||
243 | dest_ext: | |
244 | tstb LOCAL_SGN(%a1) |put back sign into exponent word | |
245 | beqs dstx_cont | |
246 | bsetb #sign_bit,LOCAL_EX(%a1) | |
247 | dstx_cont: | |
248 | clrb LOCAL_SGN(%a1) |clear out the sign byte | |
249 | ||
250 | movel #0x0c,%d0 |byte count for extended number | |
251 | exg %a0,%a1 |a0=supervisor source, a1=user dest | |
252 | bsrl mem_write |move the number to the user's memory | |
253 | rts | |
254 | ||
255 | |end |