Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/m68k/fpsp040/gen_except.S
10817 views
1
|
2
| gen_except.sa 3.7 1/16/92
3
|
4
| gen_except --- FPSP routine to detect reportable exceptions
5
|
6
| This routine compares the exception enable byte of the
7
| user_fpcr on the stack with the exception status byte
8
| of the user_fpsr.
9
|
10
| Any routine which may report an exceptions must load
11
| the stack frame in memory with the exceptional operand(s).
12
|
13
| Priority for exceptions is:
14
|
15
| Highest: bsun
16
| snan
17
| operr
18
| ovfl
19
| unfl
20
| dz
21
| inex2
22
| Lowest: inex1
23
|
24
| Note: The IEEE standard specifies that inex2 is to be
25
| reported if ovfl occurs and the ovfl enable bit is not
26
| set but the inex2 enable bit is.
27
|
28
|
29
| Copyright (C) Motorola, Inc. 1990
30
| All Rights Reserved
31
|
32
| For details on the license for this file, please see the
33
| file, README, in this same directory.
34
35
GEN_EXCEPT: |idnt 2,1 | Motorola 040 Floating Point Software Package
36
37
|section 8
38
39
#include "fpsp.h"
40
41
|xref real_trace
42
|xref fpsp_done
43
|xref fpsp_fmt_error
44
45
exc_tbl:
46
.long bsun_exc
47
.long commonE1
48
.long commonE1
49
.long ovfl_unfl
50
.long ovfl_unfl
51
.long commonE1
52
.long commonE3
53
.long commonE3
54
.long no_match
55
56
.global gen_except
57
gen_except:
58
cmpib #IDLE_SIZE-4,1(%a7) |test for idle frame
59
beq do_check |go handle idle frame
60
cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame
61
beqs unimp_x |go handle unimp frame
62
cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame
63
beqs unimp_x |go handle unimp frame
64
cmpib #BUSY_SIZE-4,1(%a7) |if size <> $60, fmt error
65
bnel fpsp_fmt_error
66
leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 so fpsp.h
67
| ;equates will work
68
| Fix up the new busy frame with entries from the unimp frame
69
|
70
movel ETEMP_EX(%a6),ETEMP_EX(%a1) |copy etemp from unimp
71
movel ETEMP_HI(%a6),ETEMP_HI(%a1) |frame to busy frame
72
movel ETEMP_LO(%a6),ETEMP_LO(%a1)
73
movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp
74
movel CMDREG1B(%a6),%d0 |fix cmd1b to make it
75
andl #0x03c30000,%d0 |work for cmd3b
76
bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2
77
lsll #5,%d1
78
swap %d1
79
orl %d1,%d0 |put it in the right place
80
bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5
81
lsll #2,%d1
82
swap %d1
83
orl %d1,%d0 |put them in the right place
84
movel %d0,CMDREG3B(%a1) |in the busy frame
85
|
86
| Or in the FPSR from the emulation with the USER_FPSR on the stack.
87
|
88
fmovel %FPSR,%d0
89
orl %d0,USER_FPSR(%a6)
90
movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits
91
orl #sx_mask,E_BYTE(%a1)
92
bra do_clean
93
94
|
95
| Frame is an unimp frame possible resulting from an fmove <ea>,fp0
96
| that caused an exception
97
|
98
| a1 is modified to point into the new frame allowing fpsp equates
99
| to be valid.
100
|
101
unimp_x:
102
cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame
103
bnes test_rev
104
leal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1
105
bras unimp_con
106
test_rev:
107
cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame
108
bnel fpsp_fmt_error |if not $28 or $30
109
leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1
110
111
unimp_con:
112
|
113
| Fix up the new unimp frame with entries from the old unimp frame
114
|
115
movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp
116
|
117
| Or in the FPSR from the emulation with the USER_FPSR on the stack.
118
|
119
fmovel %FPSR,%d0
120
orl %d0,USER_FPSR(%a6)
121
bra do_clean
122
123
|
124
| Frame is idle, so check for exceptions reported through
125
| USER_FPSR and set the unimp frame accordingly.
126
| A7 must be incremented to the point before the
127
| idle fsave vector to the unimp vector.
128
|
129
130
do_check:
131
addl #4,%a7 |point A7 back to unimp frame
132
|
133
| Or in the FPSR from the emulation with the USER_FPSR on the stack.
134
|
135
fmovel %FPSR,%d0
136
orl %d0,USER_FPSR(%a6)
137
|
138
| On a busy frame, we must clear the nmnexc bits.
139
|
140
cmpib #BUSY_SIZE-4,1(%a7) |check frame type
141
bnes check_fr |if busy, clr nmnexc
142
clrw NMNEXC(%a6) |clr nmnexc & nmcexc
143
btstb #5,CMDREG1B(%a6) |test for fmove out
144
bnes frame_com
145
movel USER_FPSR(%a6),FPSR_SHADOW(%a6) |set exc bits
146
orl #sx_mask,E_BYTE(%a6)
147
bras frame_com
148
check_fr:
149
cmpb #UNIMP_40_SIZE-4,1(%a7)
150
beqs frame_com
151
clrw NMNEXC(%a6)
152
frame_com:
153
moveb FPCR_ENABLE(%a6),%d0 |get fpcr enable byte
154
andb FPSR_EXCEPT(%a6),%d0 |and in the fpsr exc byte
155
bfffo %d0{#24:#8},%d1 |test for first set bit
156
leal exc_tbl,%a0 |load jmp table address
157
subib #24,%d1 |normalize bit offset to 0-8
158
movel (%a0,%d1.w*4),%a0 |load routine address based
159
| ;based on first enabled exc
160
jmp (%a0) |jump to routine
161
|
162
| Bsun is not possible in unimp or unsupp
163
|
164
bsun_exc:
165
bra do_clean
166
|
167
| The typical work to be done to the unimp frame to report an
168
| exception is to set the E1/E3 byte and clr the U flag.
169
| commonE1 does this for E1 exceptions, which are snan,
170
| operr, and dz. commonE3 does this for E3 exceptions, which
171
| are inex2 and inex1, and also clears the E1 exception bit
172
| left over from the unimp exception.
173
|
174
commonE1:
175
bsetb #E1,E_BYTE(%a6) |set E1 flag
176
bra commonE |go clean and exit
177
178
commonE3:
179
tstb UFLG_TMP(%a6) |test flag for unsup/unimp state
180
bnes unsE3
181
uniE3:
182
bsetb #E3,E_BYTE(%a6) |set E3 flag
183
bclrb #E1,E_BYTE(%a6) |clr E1 from unimp
184
bra commonE
185
186
unsE3:
187
tstb RES_FLG(%a6)
188
bnes unsE3_0
189
unsE3_1:
190
bsetb #E3,E_BYTE(%a6) |set E3 flag
191
unsE3_0:
192
bclrb #E1,E_BYTE(%a6) |clr E1 flag
193
movel CMDREG1B(%a6),%d0
194
andl #0x03c30000,%d0 |work for cmd3b
195
bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2
196
lsll #5,%d1
197
swap %d1
198
orl %d1,%d0 |put it in the right place
199
bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5
200
lsll #2,%d1
201
swap %d1
202
orl %d1,%d0 |put them in the right place
203
movel %d0,CMDREG3B(%a6) |in the busy frame
204
205
commonE:
206
bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp
207
bra do_clean |go clean and exit
208
|
209
| No bits in the enable byte match existing exceptions. Check for
210
| the case of the ovfl exc without the ovfl enabled, but with
211
| inex2 enabled.
212
|
213
no_match:
214
btstb #inex2_bit,FPCR_ENABLE(%a6) |check for ovfl/inex2 case
215
beqs no_exc |if clear, exit
216
btstb #ovfl_bit,FPSR_EXCEPT(%a6) |now check ovfl
217
beqs no_exc |if clear, exit
218
bras ovfl_unfl |go to unfl_ovfl to determine if
219
| ;it is an unsupp or unimp exc
220
221
| No exceptions are to be reported. If the instruction was
222
| unimplemented, no FPU restore is necessary. If it was
223
| unsupported, we must perform the restore.
224
no_exc:
225
tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
226
beqs uni_no_exc
227
uns_no_exc:
228
tstb RES_FLG(%a6) |check if frestore is needed
229
bne do_clean |if clear, no frestore needed
230
uni_no_exc:
231
moveml USER_DA(%a6),%d0-%d1/%a0-%a1
232
fmovemx USER_FP0(%a6),%fp0-%fp3
233
fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
234
unlk %a6
235
bra finish_up
236
|
237
| Unsupported Data Type Handler:
238
| Ovfl:
239
| An fmoveout that results in an overflow is reported this way.
240
| Unfl:
241
| An fmoveout that results in an underflow is reported this way.
242
|
243
| Unimplemented Instruction Handler:
244
| Ovfl:
245
| Only scosh, setox, ssinh, stwotox, and scale can set overflow in
246
| this manner.
247
| Unfl:
248
| Stwotox, setox, and scale can set underflow in this manner.
249
| Any of the other Library Routines such that f(x)=x in which
250
| x is an extended denorm can report an underflow exception.
251
| It is the responsibility of the exception-causing exception
252
| to make sure that WBTEMP is correct.
253
|
254
| The exceptional operand is in FP_SCR1.
255
|
256
ovfl_unfl:
257
tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
258
beqs ofuf_con
259
|
260
| The caller was from an unsupported data type trap. Test if the
261
| caller set CU_ONLY. If so, the exceptional operand is expected in
262
| FPTEMP, rather than WBTEMP.
263
|
264
tstb CU_ONLY(%a6) |test if inst is cu-only
265
beq unsE3
266
| move.w #$fe,CU_SAVEPC(%a6)
267
clrb CU_SAVEPC(%a6)
268
bsetb #E1,E_BYTE(%a6) |set E1 exception flag
269
movew ETEMP_EX(%a6),FPTEMP_EX(%a6)
270
movel ETEMP_HI(%a6),FPTEMP_HI(%a6)
271
movel ETEMP_LO(%a6),FPTEMP_LO(%a6)
272
bsetb #fptemp15_bit,DTAG(%a6) |set fpte15
273
bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp
274
bra do_clean |go clean and exit
275
276
ofuf_con:
277
moveb (%a7),VER_TMP(%a6) |save version number
278
cmpib #BUSY_SIZE-4,1(%a7) |check for busy frame
279
beqs busy_fr |if unimp, grow to busy
280
cmpib #VER_40,(%a7) |test for orig unimp frame
281
bnes try_41 |if not, test for rev frame
282
moveql #13,%d0 |need to zero 14 lwords
283
bras ofuf_fin
284
try_41:
285
cmpib #VER_41,(%a7) |test for rev unimp frame
286
bnel fpsp_fmt_error |if neither, exit with error
287
moveql #11,%d0 |need to zero 12 lwords
288
289
ofuf_fin:
290
clrl (%a7)
291
loop1:
292
clrl -(%a7) |clear and dec a7
293
dbra %d0,loop1
294
moveb VER_TMP(%a6),(%a7)
295
moveb #BUSY_SIZE-4,1(%a7) |write busy fmt word.
296
busy_fr:
297
movel FP_SCR1(%a6),WBTEMP_EX(%a6) |write
298
movel FP_SCR1+4(%a6),WBTEMP_HI(%a6) |exceptional op to
299
movel FP_SCR1+8(%a6),WBTEMP_LO(%a6) |wbtemp
300
bsetb #E3,E_BYTE(%a6) |set E3 flag
301
bclrb #E1,E_BYTE(%a6) |make sure E1 is clear
302
bclrb #UFLAG,T_BYTE(%a6) |clr U flag
303
movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
304
orl #sx_mask,E_BYTE(%a6)
305
movel CMDREG1B(%a6),%d0 |fix cmd1b to make it
306
andl #0x03c30000,%d0 |work for cmd3b
307
bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2
308
lsll #5,%d1
309
swap %d1
310
orl %d1,%d0 |put it in the right place
311
bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5
312
lsll #2,%d1
313
swap %d1
314
orl %d1,%d0 |put them in the right place
315
movel %d0,CMDREG3B(%a6) |in the busy frame
316
317
|
318
| Check if the frame to be restored is busy or unimp.
319
|** NOTE *** Bug fix for errata (0d43b #3)
320
| If the frame is unimp, we must create a busy frame to
321
| fix the bug with the nmnexc bits in cases in which they
322
| are set by a previous instruction and not cleared by
323
| the save. The frame will be unimp only if the final
324
| instruction in an emulation routine caused the exception
325
| by doing an fmove <ea>,fp0. The exception operand, in
326
| internal format, is in fptemp.
327
|
328
do_clean:
329
cmpib #UNIMP_40_SIZE-4,1(%a7)
330
bnes do_con
331
moveql #13,%d0 |in orig, need to zero 14 lwords
332
bras do_build
333
do_con:
334
cmpib #UNIMP_41_SIZE-4,1(%a7)
335
bnes do_restore |frame must be busy
336
moveql #11,%d0 |in rev, need to zero 12 lwords
337
338
do_build:
339
moveb (%a7),VER_TMP(%a6)
340
clrl (%a7)
341
loop2:
342
clrl -(%a7) |clear and dec a7
343
dbra %d0,loop2
344
|
345
| Use a1 as pointer into new frame. a6 is not correct if an unimp or
346
| busy frame was created as the result of an exception on the final
347
| instruction of an emulation routine.
348
|
349
| We need to set the nmcexc bits if the exception is E1. Otherwise,
350
| the exc taken will be inex2.
351
|
352
leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 for new frame
353
moveb VER_TMP(%a6),(%a7) |write busy fmt word
354
moveb #BUSY_SIZE-4,1(%a7)
355
movel FP_SCR1(%a6),WBTEMP_EX(%a1) |write
356
movel FP_SCR1+4(%a6),WBTEMP_HI(%a1) |exceptional op to
357
movel FP_SCR1+8(%a6),WBTEMP_LO(%a1) |wbtemp
358
| btst.b #E1,E_BYTE(%a1)
359
| beq.b do_restore
360
bfextu USER_FPSR(%a6){#17:#4},%d0 |get snan/operr/ovfl/unfl bits
361
bfins %d0,NMCEXC(%a1){#4:#4} |and insert them in nmcexc
362
movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits
363
orl #sx_mask,E_BYTE(%a1)
364
365
do_restore:
366
moveml USER_DA(%a6),%d0-%d1/%a0-%a1
367
fmovemx USER_FP0(%a6),%fp0-%fp3
368
fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
369
frestore (%a7)+
370
tstb RES_FLG(%a6) |RES_FLG indicates a "continuation" frame
371
beq cont
372
bsr bug1384
373
cont:
374
unlk %a6
375
|
376
| If trace mode enabled, then go to trace handler. This handler
377
| cannot have any fp instructions. If there are fp inst's and an
378
| exception has been restored into the machine then the exception
379
| will occur upon execution of the fp inst. This is not desirable
380
| in the kernel (supervisor mode). See MC68040 manual Section 9.3.8.
381
|
382
finish_up:
383
btstb #7,(%a7) |test T1 in SR
384
bnes g_trace
385
btstb #6,(%a7) |test T0 in SR
386
bnes g_trace
387
bral fpsp_done
388
|
389
| Change integer stack to look like trace stack
390
| The address of the instruction that caused the
391
| exception is already in the integer stack (is
392
| the same as the saved friar)
393
|
394
| If the current frame is already a 6-word stack then all
395
| that needs to be done is to change the vector# to TRACE.
396
| If the frame is only a 4-word stack (meaning we got here
397
| on an Unsupported data type exception), then we need to grow
398
| the stack an extra 2 words and get the FPIAR from the FPU.
399
|
400
g_trace:
401
bftst EXC_VEC-4(%sp){#0:#4}
402
bne g_easy
403
404
subw #4,%sp | make room
405
movel 4(%sp),(%sp)
406
movel 8(%sp),4(%sp)
407
subw #BUSY_SIZE,%sp
408
fsave (%sp)
409
fmovel %fpiar,BUSY_SIZE+EXC_EA-4(%sp)
410
frestore (%sp)
411
addw #BUSY_SIZE,%sp
412
413
g_easy:
414
movew #TRACE_VEC,EXC_VEC-4(%a7)
415
bral real_trace
416
|
417
| This is a work-around for hardware bug 1384.
418
|
419
bug1384:
420
link %a5,#0
421
fsave -(%sp)
422
cmpib #0x41,(%sp) | check for correct frame
423
beq frame_41
424
bgt nofix | if more advanced mask, do nada
425
426
frame_40:
427
tstb 1(%sp) | check to see if idle
428
bne notidle
429
idle40:
430
clrl (%sp) | get rid of old fsave frame
431
movel %d1,USER_D1(%a6) | save d1
432
movew #8,%d1 | place unimp frame instead
433
loop40: clrl -(%sp)
434
dbra %d1,loop40
435
movel USER_D1(%a6),%d1 | restore d1
436
movel #0x40280000,-(%sp)
437
frestore (%sp)+
438
unlk %a5
439
rts
440
441
frame_41:
442
tstb 1(%sp) | check to see if idle
443
bne notidle
444
idle41:
445
clrl (%sp) | get rid of old fsave frame
446
movel %d1,USER_D1(%a6) | save d1
447
movew #10,%d1 | place unimp frame instead
448
loop41: clrl -(%sp)
449
dbra %d1,loop41
450
movel USER_D1(%a6),%d1 | restore d1
451
movel #0x41300000,-(%sp)
452
frestore (%sp)+
453
unlk %a5
454
rts
455
456
notidle:
457
bclrb #etemp15_bit,-40(%a5)
458
frestore (%sp)+
459
unlk %a5
460
rts
461
462
nofix:
463
frestore (%sp)+
464
unlk %a5
465
rts
466
467
|end
468
469