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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
|
* $OpenBSD: x_operr.sa,v 1.3 2001/09/20 17:02:30 mpech Exp $
* $NetBSD: x_operr.sa,v 1.4 1994/10/26 07:50:24 cgd Exp $
* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
* M68000 Hi-Performance Microprocessor Division
* M68040 Software Package
*
* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
* All rights reserved.
*
* THE SOFTWARE is provided on an "AS IS" basis and without warranty.
* To the maximum extent permitted by applicable law,
* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
* PARTICULAR PURPOSE and any warranty against infringement with
* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
* and any accompanying written materials.
*
* To the maximum extent permitted by applicable law,
* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
* SOFTWARE. Motorola assumes no responsibility for the maintenance
* and support of the SOFTWARE.
*
* You are hereby granted a copyright license to use, modify, and
* distribute the SOFTWARE so long as this entire notice is retained
* without alteration in any modified and/or redistributed versions,
* and that such modified versions are clearly identified as such.
* No licenses are granted by implication, estoppel or otherwise
* under any patents or trademarks of Motorola, Inc.
*
* x_operr.sa 3.5 7/1/91
*
* fpsp_operr --- FPSP handler for operand error exception
*
* See 68040 User's Manual pp. 9-44f
*
* Note 1: For trap disabled 040 does the following:
* If the dest is a fp reg, then an extended precision non_signaling
* NAN is stored in the dest reg. If the dest format is b, w, or l and
* the source op is a NAN, then garbage is stored as the result (actually
* the upper 32 bits of the mantissa are sent to the integer unit). If
* the dest format is integer (b, w, l) and the operr is caused by
* integer overflow, or the source op is inf, then the result stored is
* garbage.
* There are three cases in which operr is incorrectly signaled on the
* 040. This occurs for move_out of format b, w, or l for the largest
* negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
*
* On opclass = 011 fmove.(b,w,l) that causes a conversion
* overflow -> OPERR, the exponent in wbte (and fpte) is:
* byte 56 - (62 - exp)
* word 48 - (62 - exp)
* long 32 - (62 - exp)
*
* where exp = (true exp) - 1
*
* So, wbtemp and fptemp will contain the following on erroneoulsy
* signalled operr:
* fpts = 1
* fpte = $4000 (15 bit externally)
* byte fptm = $ffffffff ffffff80
* word fptm = $ffffffff ffff8000
* long fptm = $ffffffff 80000000
*
* Note 2: For trap enabled 040 does the following:
* If the inst is move_out, then same as Note 1.
* If the inst is not move_out, the dest is not modified.
* The exceptional operand is not defined for integer overflow
* during a move_out.
*
X_OPERR IDNT 2,1 Motorola 040 Floating Point Software Package
section 8
include fpsp.h
xref mem_write
xref real_operr
xref real_inex
xref get_fline
xref fpsp_done
xref reg_dest
xdef fpsp_operr
fpsp_operr:
*
link a6,#-LOCAL_SIZE
fsave -(a7)
movem.l d0-d1/a0-a1,USER_DA(a6)
fmovem.x fp0-fp3,USER_FP0(a6)
fmovem.l fpcr/fpsr/fpiar,USER_FPCR(a6)
*
* Check if this is an opclass 3 instruction.
* If so, fall through, else branch to operr_end
*
btst.b #TFLAG,T_BYTE(a6)
beq.b operr_end
*
* If the destination size is B,W,or L, the operr must be
* handled here.
*
move.l CMDREG1B(a6),d0
bfextu d0{3:3},d0 ;0=long, 4=word, 6=byte
tst.b d0 ;determine size; check long
beq.w operr_long
cmpi.b #4,d0 ;check word
beq.w operr_word
cmpi.b #6,d0 ;check byte
beq.w operr_byte
*
* The size is not B,W,or L, so the operr is handled by the
* kernel handler. Set the operr bits and clean up, leaving
* only the integer exception frame on the stack, and the
* fpu in the original exceptional state.
*
operr_end:
bset.b #operr_bit,FPSR_EXCEPT(a6)
bset.b #aiop_bit,FPSR_AEXCEPT(a6)
movem.l USER_DA(a6),d0-d1/a0-a1
fmovem.x USER_FP0(a6),fp0-fp3
fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
frestore (a7)+
unlk a6
bra.l real_operr
operr_long:
moveq.l #4,d1 ;write size to d1
move.b STAG(a6),d0 ;test stag for nan
andi.b #$e0,d0 ;clr all but tag
cmpi.b #$60,d0 ;check for nan
beq operr_nan
cmpi.l #$80000000,FPTEMP_LO(a6) ;test if ls lword is special
bne.b chklerr ;if not equal, check for incorrect operr
bsr check_upper ;check if exp and ms mant are special
tst.l d0
bne.b chklerr ;if d0 is true, check for incorrect operr
move.l #$80000000,d0 ;store special case result
bsr operr_store
bra.w not_enabled ;clean and exit
*
* CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
*
chklerr:
move.w FPTEMP_EX(a6),d0
and.w #$7FFF,d0 ;ignore sign bit
cmp.w #$3FFE,d0 ;this is the only possible exponent value
bne.b chklerr2
fixlong:
move.l FPTEMP_LO(a6),d0
bsr operr_store
bra.w not_enabled
chklerr2:
move.w FPTEMP_EX(a6),d0
and.w #$7FFF,d0 ;ignore sign bit
cmp.w #$4000,d0
bcc.w store_max ;exponent out of range
move.l FPTEMP_LO(a6),d0
and.l #$7FFF0000,d0 ;look for all 1's on bits 30-16
cmp.l #$7FFF0000,d0
beq.b fixlong
tst.l FPTEMP_LO(a6)
bpl.b chklepos
cmp.l #$FFFFFFFF,FPTEMP_HI(a6)
beq.b fixlong
bra.w store_max
chklepos:
tst.l FPTEMP_HI(a6)
beq.b fixlong
bra.w store_max
operr_word:
moveq.l #2,d1 ;write size to d1
move.b STAG(a6),d0 ;test stag for nan
andi.b #$e0,d0 ;clr all but tag
cmpi.b #$60,d0 ;check for nan
beq.w operr_nan
cmpi.l #$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special
bne.b chkwerr ;if not equal, check for incorrect operr
bsr check_upper ;check if exp and ms mant are special
tst.l d0
bne.b chkwerr ;if d0 is true, check for incorrect operr
move.l #$80000000,d0 ;store special case result
bsr operr_store
bra.w not_enabled ;clean and exit
*
* CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
*
chkwerr:
move.w FPTEMP_EX(a6),d0
and.w #$7FFF,d0 ;ignore sign bit
cmp.w #$3FFE,d0 ;this is the only possible exponent value
bne.b store_max
move.l FPTEMP_LO(a6),d0
swap d0
bsr operr_store
bra.w not_enabled
operr_byte:
moveq.l #1,d1 ;write size to d1
move.b STAG(a6),d0 ;test stag for nan
andi.b #$e0,d0 ;clr all but tag
cmpi.b #$60,d0 ;check for nan
beq.b operr_nan
cmpi.l #$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special
bne.b chkberr ;if not equal, check for incorrect operr
bsr check_upper ;check if exp and ms mant are special
tst.l d0
bne.b chkberr ;if d0 is true, check for incorrect operr
move.l #$80000000,d0 ;store special case result
bsr operr_store
bra.w not_enabled ;clean and exit
*
* CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
*
chkberr:
move.w FPTEMP_EX(a6),d0
and.w #$7FFF,d0 ;ignore sign bit
cmp.w #$3FFE,d0 ;this is the only possible exponent value
bne.b store_max
move.l FPTEMP_LO(a6),d0
asl.l #8,d0
swap d0
bsr operr_store
bra.w not_enabled
*
* This operr condition is not of the special case. Set operr
* and aiop and write the portion of the nan to memory for the
* given size.
*
operr_nan:
or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
move.l ETEMP_HI(a6),d0 ;output will be from upper 32 bits
bsr operr_store
bra end_operr
*
* Store_max loads the max pos or negative for the size, sets
* the operr and aiop bits, and clears inex and ainex, incorrectly
* set by the 040.
*
store_max:
or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
bclr.b #inex2_bit,FPSR_EXCEPT(a6)
bclr.b #ainex_bit,FPSR_AEXCEPT(a6)
fmove.l #0,FPSR
tst.w FPTEMP_EX(a6) ;check sign
blt.b load_neg
move.l #$7fffffff,d0
bsr operr_store
bra end_operr
load_neg:
move.l #$80000000,d0
bsr operr_store
bra end_operr
*
* This routine stores the data in d0, for the given size in d1,
* to memory or data register as required. A read of the fline
* is required to determine the destination.
*
operr_store:
move.l d0,L_SCR1(a6) ;move write data to L_SCR1
move.l d1,-(a7) ;save register size
bsr.l get_fline ;fline returned in d0
move.l (a7)+,d1
bftst d0{26:3} ;if mode is zero, dest is Dn
bne.b dest_mem
*
* Destination is Dn. Get register number from d0. Data is on
* the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
*
andi.l #7,d0 ;isolate register number
cmpi.l #4,d1
beq.b op_long ;the most frequent case
cmpi.l #2,d1
bne.b op_con
or.l #8,d0
bra.b op_con
op_long:
or.l #$10,d0
op_con:
move.l d0,d1 ;format size:reg for reg_dest
bra.l reg_dest ;call to reg_dest returns to caller
* ;of operr_store
*
* Destination is memory. Get <ea> from integer exception frame
* and call mem_write.
*
dest_mem:
lea.l L_SCR1(a6),a0 ;put ptr to write data in a0
move.l EXC_EA(a6),a1 ;put user destination address in a1
move.l d1,d0 ;put size in d0
bsr.l mem_write
rts
*
* Check the exponent for $c000 and the upper 32 bits of the
* mantissa for $ffffffff. If both are true, return d0 clr
* and store the lower n bits of the least lword of FPTEMP
* to d0 for write out. If not, it is a real operr, and set d0.
*
check_upper:
cmpi.l #$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's
bne.b true_operr ;if not all 1's then was true operr
cmpi.w #$c000,FPTEMP_EX(a6) ;check if incorrectly signalled
beq.b not_true_operr ;branch if not true operr
cmpi.w #$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled
beq.b not_true_operr ;branch if not true operr
true_operr:
move.l #1,d0 ;signal real operr
rts
not_true_operr:
clr.l d0 ;signal no real operr
rts
*
* End_operr tests for operr enabled. If not, it cleans up the stack
* and does an rte. If enabled, it cleans up the stack and branches
* to the kernel operr handler with only the integer exception
* frame on the stack and the fpu in the original exceptional state
* with correct data written to the destination.
*
end_operr:
btst.b #operr_bit,FPCR_ENABLE(a6)
beq.b not_enabled
enabled:
movem.l USER_DA(a6),d0-d1/a0-a1
fmovem.x USER_FP0(a6),fp0-fp3
fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
frestore (a7)+
unlk a6
bra.l real_operr
not_enabled:
*
* It is possible to have either inex2 or inex1 exceptions with the
* operr. If the inex enable bit is set in the FPCR, and either
* inex2 or inex1 occurred, we must clean up and branch to the
* real inex handler.
*
ck_inex:
move.b FPCR_ENABLE(a6),d0
and.b FPSR_EXCEPT(a6),d0
andi.b #$3,d0
beq.w operr_exit
*
* Inexact enabled and reported, and we must take an inexact exception.
*
take_inex:
move.b #INEX_VEC,EXC_VEC+1(a6)
move.l USER_FPSR(a6),FPSR_SHADOW(a6)
or.l #sx_mask,E_BYTE(a6)
movem.l USER_DA(a6),d0-d1/a0-a1
fmovem.x USER_FP0(a6),fp0-fp3
fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
frestore (a7)+
unlk a6
bra.l real_inex
*
* Since operr is only an E1 exception, there is no need to frestore
* any state back to the fpu.
*
operr_exit:
movem.l USER_DA(a6),d0-d1/a0-a1
fmovem.x USER_FP0(a6),fp0-fp3
fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
unlk a6
bra.l fpsp_done
end
|