Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/m68k/fpsp040/skeleton.S
10817 views
1
|
2
| skeleton.sa 3.2 4/26/91
3
|
4
| This file contains code that is system dependent and will
5
| need to be modified to install the FPSP.
6
|
7
| Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
8
| Put any target system specific handling that must be done immediately
9
| before the jump instruction. If there no handling necessary, then
10
| the 'fpsp_xxxx' handler entry point should be placed in the exception
11
| table so that the 'jmp' can be eliminated. If the FPSP determines that the
12
| exception is one that must be reported then there will be a
13
| return from the package by a 'jmp real_xxxx'. At that point
14
| the machine state will be identical to the state before
15
| the FPSP was entered. In particular, whatever condition
16
| that caused the exception will still be pending when the FPSP
17
| package returns. Thus, there will be system specific code
18
| to handle the exception.
19
|
20
| If the exception was completely handled by the package, then
21
| the return will be via a 'jmp fpsp_done'. Unless there is
22
| OS specific work to be done (such as handling a context switch or
23
| interrupt) the user program can be resumed via 'rte'.
24
|
25
| In the following skeleton code, some typical 'real_xxxx' handling
26
| code is shown. This code may need to be moved to an appropriate
27
| place in the target system, or rewritten.
28
|
29
30
| Copyright (C) Motorola, Inc. 1990
31
| All Rights Reserved
32
|
33
| For details on the license for this file, please see the
34
| file, README, in this same directory.
35
36
|
37
| Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
38
|
39
40
#include <linux/linkage.h>
41
#include <asm/entry.h>
42
#include <asm/asm-offsets.h>
43
44
|SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package
45
46
|section 15
47
|
48
| The following counters are used for standalone testing
49
|
50
51
|section 8
52
53
#include "fpsp.h"
54
55
|xref b1238_fix
56
57
|
58
| Divide by Zero exception
59
|
60
| All dz exceptions are 'real', hence no fpsp_dz entry point.
61
|
62
.global dz
63
.global real_dz
64
dz:
65
real_dz:
66
link %a6,#-LOCAL_SIZE
67
fsave -(%sp)
68
bclrb #E1,E_BYTE(%a6)
69
frestore (%sp)+
70
unlk %a6
71
72
SAVE_ALL_INT
73
GET_CURRENT(%d0)
74
movel %sp,%sp@- | stack frame pointer argument
75
bsrl trap_c
76
addql #4,%sp
77
bral ret_from_exception
78
79
|
80
| Inexact exception
81
|
82
| All inexact exceptions are real, but the 'real' handler
83
| will probably want to clear the pending exception.
84
| The provided code will clear the E3 exception (if pending),
85
| otherwise clear the E1 exception. The frestore is not really
86
| necessary for E1 exceptions.
87
|
88
| Code following the 'inex' label is to handle bug #1232. In this
89
| bug, if an E1 snan, ovfl, or unfl occurred, and the process was
90
| swapped out before taking the exception, the exception taken on
91
| return was inex, rather than the correct exception. The snan, ovfl,
92
| and unfl exception to be taken must not have been enabled. The
93
| fix is to check for E1, and the existence of one of snan, ovfl,
94
| or unfl bits set in the fpsr. If any of these are set, branch
95
| to the appropriate handler for the exception in the fpsr. Note
96
| that this fix is only for d43b parts, and is skipped if the
97
| version number is not $40.
98
|
99
|
100
.global real_inex
101
.global inex
102
inex:
103
link %a6,#-LOCAL_SIZE
104
fsave -(%sp)
105
cmpib #VER_40,(%sp) |test version number
106
bnes not_fmt40
107
fmovel %fpsr,-(%sp)
108
btstb #E1,E_BYTE(%a6) |test for E1 set
109
beqs not_b1232
110
btstb #snan_bit,2(%sp) |test for snan
111
beq inex_ckofl
112
addl #4,%sp
113
frestore (%sp)+
114
unlk %a6
115
bra snan
116
inex_ckofl:
117
btstb #ovfl_bit,2(%sp) |test for ovfl
118
beq inex_ckufl
119
addl #4,%sp
120
frestore (%sp)+
121
unlk %a6
122
bra ovfl
123
inex_ckufl:
124
btstb #unfl_bit,2(%sp) |test for unfl
125
beq not_b1232
126
addl #4,%sp
127
frestore (%sp)+
128
unlk %a6
129
bra unfl
130
131
|
132
| We do not have the bug 1232 case. Clean up the stack and call
133
| real_inex.
134
|
135
not_b1232:
136
addl #4,%sp
137
frestore (%sp)+
138
unlk %a6
139
140
real_inex:
141
142
link %a6,#-LOCAL_SIZE
143
fsave -(%sp)
144
not_fmt40:
145
bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
146
beqs inex_cke1
147
|
148
| Clear dirty bit on dest resister in the frame before branching
149
| to b1238_fix.
150
|
151
moveml %d0/%d1,USER_DA(%a6)
152
bfextu CMDREG1B(%a6){#6:#3},%d0 |get dest reg no
153
bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
154
bsrl b1238_fix |test for bug1238 case
155
moveml USER_DA(%a6),%d0/%d1
156
bras inex_done
157
inex_cke1:
158
bclrb #E1,E_BYTE(%a6)
159
inex_done:
160
frestore (%sp)+
161
unlk %a6
162
163
SAVE_ALL_INT
164
GET_CURRENT(%d0)
165
movel %sp,%sp@- | stack frame pointer argument
166
bsrl trap_c
167
addql #4,%sp
168
bral ret_from_exception
169
170
|
171
| Overflow exception
172
|
173
|xref fpsp_ovfl
174
.global real_ovfl
175
.global ovfl
176
ovfl:
177
jmp fpsp_ovfl
178
real_ovfl:
179
180
link %a6,#-LOCAL_SIZE
181
fsave -(%sp)
182
bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
183
bnes ovfl_done
184
bclrb #E1,E_BYTE(%a6)
185
ovfl_done:
186
frestore (%sp)+
187
unlk %a6
188
189
SAVE_ALL_INT
190
GET_CURRENT(%d0)
191
movel %sp,%sp@- | stack frame pointer argument
192
bsrl trap_c
193
addql #4,%sp
194
bral ret_from_exception
195
196
|
197
| Underflow exception
198
|
199
|xref fpsp_unfl
200
.global real_unfl
201
.global unfl
202
unfl:
203
jmp fpsp_unfl
204
real_unfl:
205
206
link %a6,#-LOCAL_SIZE
207
fsave -(%sp)
208
bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
209
bnes unfl_done
210
bclrb #E1,E_BYTE(%a6)
211
unfl_done:
212
frestore (%sp)+
213
unlk %a6
214
215
SAVE_ALL_INT
216
GET_CURRENT(%d0)
217
movel %sp,%sp@- | stack frame pointer argument
218
bsrl trap_c
219
addql #4,%sp
220
bral ret_from_exception
221
222
|
223
| Signalling NAN exception
224
|
225
|xref fpsp_snan
226
.global real_snan
227
.global snan
228
snan:
229
jmp fpsp_snan
230
real_snan:
231
link %a6,#-LOCAL_SIZE
232
fsave -(%sp)
233
bclrb #E1,E_BYTE(%a6) |snan is always an E1 exception
234
frestore (%sp)+
235
unlk %a6
236
237
SAVE_ALL_INT
238
GET_CURRENT(%d0)
239
movel %sp,%sp@- | stack frame pointer argument
240
bsrl trap_c
241
addql #4,%sp
242
bral ret_from_exception
243
244
|
245
| Operand Error exception
246
|
247
|xref fpsp_operr
248
.global real_operr
249
.global operr
250
operr:
251
jmp fpsp_operr
252
real_operr:
253
link %a6,#-LOCAL_SIZE
254
fsave -(%sp)
255
bclrb #E1,E_BYTE(%a6) |operr is always an E1 exception
256
frestore (%sp)+
257
unlk %a6
258
259
SAVE_ALL_INT
260
GET_CURRENT(%d0)
261
movel %sp,%sp@- | stack frame pointer argument
262
bsrl trap_c
263
addql #4,%sp
264
bral ret_from_exception
265
266
267
|
268
| BSUN exception
269
|
270
| This sample handler simply clears the nan bit in the FPSR.
271
|
272
|xref fpsp_bsun
273
.global real_bsun
274
.global bsun
275
bsun:
276
jmp fpsp_bsun
277
real_bsun:
278
link %a6,#-LOCAL_SIZE
279
fsave -(%sp)
280
bclrb #E1,E_BYTE(%a6) |bsun is always an E1 exception
281
fmovel %FPSR,-(%sp)
282
bclrb #nan_bit,(%sp)
283
fmovel (%sp)+,%FPSR
284
frestore (%sp)+
285
unlk %a6
286
287
SAVE_ALL_INT
288
GET_CURRENT(%d0)
289
movel %sp,%sp@- | stack frame pointer argument
290
bsrl trap_c
291
addql #4,%sp
292
bral ret_from_exception
293
294
|
295
| F-line exception
296
|
297
| A 'real' F-line exception is one that the FPSP isn't supposed to
298
| handle. E.g. an instruction with a co-processor ID that is not 1.
299
|
300
|
301
|xref fpsp_fline
302
.global real_fline
303
.global fline
304
fline:
305
jmp fpsp_fline
306
real_fline:
307
308
SAVE_ALL_INT
309
GET_CURRENT(%d0)
310
movel %sp,%sp@- | stack frame pointer argument
311
bsrl trap_c
312
addql #4,%sp
313
bral ret_from_exception
314
315
|
316
| Unsupported data type exception
317
|
318
|xref fpsp_unsupp
319
.global real_unsupp
320
.global unsupp
321
unsupp:
322
jmp fpsp_unsupp
323
real_unsupp:
324
link %a6,#-LOCAL_SIZE
325
fsave -(%sp)
326
bclrb #E1,E_BYTE(%a6) |unsupp is always an E1 exception
327
frestore (%sp)+
328
unlk %a6
329
330
SAVE_ALL_INT
331
GET_CURRENT(%d0)
332
movel %sp,%sp@- | stack frame pointer argument
333
bsrl trap_c
334
addql #4,%sp
335
bral ret_from_exception
336
337
|
338
| Trace exception
339
|
340
.global real_trace
341
real_trace:
342
|
343
bral trap
344
345
|
346
| fpsp_fmt_error --- exit point for frame format error
347
|
348
| The fpu stack frame does not match the frames existing
349
| or planned at the time of this writing. The fpsp is
350
| unable to handle frame sizes not in the following
351
| version:size pairs:
352
|
353
| {4060, 4160} - busy frame
354
| {4028, 4130} - unimp frame
355
| {4000, 4100} - idle frame
356
|
357
| This entry point simply holds an f-line illegal value.
358
| Replace this with a call to your kernel panic code or
359
| code to handle future revisions of the fpu.
360
|
361
.global fpsp_fmt_error
362
fpsp_fmt_error:
363
364
.long 0xf27f0000 |f-line illegal
365
366
|
367
| fpsp_done --- FPSP exit point
368
|
369
| The exception has been handled by the package and we are ready
370
| to return to user mode, but there may be OS specific code
371
| to execute before we do. If there is, do it now.
372
|
373
|
374
375
.global fpsp_done
376
fpsp_done:
377
btst #0x5,%sp@ | supervisor bit set in saved SR?
378
beq .Lnotkern
379
rte
380
.Lnotkern:
381
SAVE_ALL_INT
382
GET_CURRENT(%d0)
383
| deliver signals, reschedule etc..
384
jra ret_from_exception
385
386
|
387
| mem_write --- write to user or supervisor address space
388
|
389
| Writes to memory while in supervisor mode. copyout accomplishes
390
| this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function.
391
| If you don't have copyout, use the local copy of the function below.
392
|
393
| a0 - supervisor source address
394
| a1 - user destination address
395
| d0 - number of bytes to write (maximum count is 12)
396
|
397
| The supervisor source address is guaranteed to point into the supervisor
398
| stack. The result is that a UNIX
399
| process is allowed to sleep as a consequence of a page fault during
400
| copyout. The probability of a page fault is exceedingly small because
401
| the 68040 always reads the destination address and thus the page
402
| faults should have already been handled.
403
|
404
| If the EXC_SR shows that the exception was from supervisor space,
405
| then just do a dumb (and slow) memory move. In a UNIX environment
406
| there shouldn't be any supervisor mode floating point exceptions.
407
|
408
.global mem_write
409
mem_write:
410
btstb #5,EXC_SR(%a6) |check for supervisor state
411
beqs user_write
412
super_write:
413
moveb (%a0)+,(%a1)+
414
subql #1,%d0
415
bnes super_write
416
rts
417
user_write:
418
movel %d1,-(%sp) |preserve d1 just in case
419
movel %d0,-(%sp)
420
movel %a1,-(%sp)
421
movel %a0,-(%sp)
422
jsr copyout
423
addw #12,%sp
424
movel (%sp)+,%d1
425
rts
426
|
427
| mem_read --- read from user or supervisor address space
428
|
429
| Reads from memory while in supervisor mode. copyin accomplishes
430
| this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function.
431
| If you don't have copyin, use the local copy of the function below.
432
|
433
| The FPSP calls mem_read to read the original F-line instruction in order
434
| to extract the data register number when the 'Dn' addressing mode is
435
| used.
436
|
437
|Input:
438
| a0 - user source address
439
| a1 - supervisor destination address
440
| d0 - number of bytes to read (maximum count is 12)
441
|
442
| Like mem_write, mem_read always reads with a supervisor
443
| destination address on the supervisor stack. Also like mem_write,
444
| the EXC_SR is checked and a simple memory copy is done if reading
445
| from supervisor space is indicated.
446
|
447
.global mem_read
448
mem_read:
449
btstb #5,EXC_SR(%a6) |check for supervisor state
450
beqs user_read
451
super_read:
452
moveb (%a0)+,(%a1)+
453
subql #1,%d0
454
bnes super_read
455
rts
456
user_read:
457
movel %d1,-(%sp) |preserve d1 just in case
458
movel %d0,-(%sp)
459
movel %a1,-(%sp)
460
movel %a0,-(%sp)
461
jsr copyin
462
addw #12,%sp
463
movel (%sp)+,%d1
464
rts
465
466
|
467
| Use these routines if your kernel doesn't have copyout/copyin equivalents.
468
| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
469
| and copyin overwrites SFC.
470
|
471
copyout:
472
movel 4(%sp),%a0 | source
473
movel 8(%sp),%a1 | destination
474
movel 12(%sp),%d0 | count
475
subl #1,%d0 | dec count by 1 for dbra
476
movel #1,%d1
477
478
| DFC is already set
479
| movec %d1,%DFC | set dfc for user data space
480
moreout:
481
moveb (%a0)+,%d1 | fetch supervisor byte
482
out_ea:
483
movesb %d1,(%a1)+ | write user byte
484
dbf %d0,moreout
485
rts
486
487
copyin:
488
movel 4(%sp),%a0 | source
489
movel 8(%sp),%a1 | destination
490
movel 12(%sp),%d0 | count
491
subl #1,%d0 | dec count by 1 for dbra
492
movel #1,%d1
493
| SFC is already set
494
| movec %d1,%SFC | set sfc for user space
495
morein:
496
in_ea:
497
movesb (%a0)+,%d1 | fetch user byte
498
moveb %d1,(%a1)+ | write supervisor byte
499
dbf %d0,morein
500
rts
501
502
.section .fixup,#alloc,#execinstr
503
.even
504
1:
505
jbra fpsp040_die
506
507
.section __ex_table,#alloc
508
.align 4
509
510
.long in_ea,1b
511
.long out_ea,1b
512
513
|end
514
515