11da177e4SLinus Torvalds| 21da177e4SLinus Torvalds| skeleton.sa 3.2 4/26/91 31da177e4SLinus Torvalds| 41da177e4SLinus Torvalds| This file contains code that is system dependent and will 51da177e4SLinus Torvalds| need to be modified to install the FPSP. 61da177e4SLinus Torvalds| 71da177e4SLinus Torvalds| Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'. 81da177e4SLinus Torvalds| Put any target system specific handling that must be done immediately 91da177e4SLinus Torvalds| before the jump instruction. If there no handling necessary, then 101da177e4SLinus Torvalds| the 'fpsp_xxxx' handler entry point should be placed in the exception 111da177e4SLinus Torvalds| table so that the 'jmp' can be eliminated. If the FPSP determines that the 121da177e4SLinus Torvalds| exception is one that must be reported then there will be a 131da177e4SLinus Torvalds| return from the package by a 'jmp real_xxxx'. At that point 141da177e4SLinus Torvalds| the machine state will be identical to the state before 151da177e4SLinus Torvalds| the FPSP was entered. In particular, whatever condition 161da177e4SLinus Torvalds| that caused the exception will still be pending when the FPSP 171da177e4SLinus Torvalds| package returns. Thus, there will be system specific code 181da177e4SLinus Torvalds| to handle the exception. 191da177e4SLinus Torvalds| 201da177e4SLinus Torvalds| If the exception was completely handled by the package, then 211da177e4SLinus Torvalds| the return will be via a 'jmp fpsp_done'. Unless there is 221da177e4SLinus Torvalds| OS specific work to be done (such as handling a context switch or 231da177e4SLinus Torvalds| interrupt) the user program can be resumed via 'rte'. 241da177e4SLinus Torvalds| 251da177e4SLinus Torvalds| In the following skeleton code, some typical 'real_xxxx' handling 261da177e4SLinus Torvalds| code is shown. This code may need to be moved to an appropriate 271da177e4SLinus Torvalds| place in the target system, or rewritten. 281da177e4SLinus Torvalds| 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds| Copyright (C) Motorola, Inc. 1990 311da177e4SLinus Torvalds| All Rights Reserved 321da177e4SLinus Torvalds| 33e00d82d0SMatt Waddel| For details on the license for this file, please see the 34e00d82d0SMatt Waddel| file, README, in this same directory. 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds| 371da177e4SLinus Torvalds| Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk) 381da177e4SLinus Torvalds| 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds#include <linux/linkage.h> 411da177e4SLinus Torvalds#include <asm/entry.h> 420013a854SSam Ravnborg#include <asm/asm-offsets.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds|SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds |section 15 471da177e4SLinus Torvalds| 481da177e4SLinus Torvalds| The following counters are used for standalone testing 491da177e4SLinus Torvalds| 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds |section 8 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds#include "fpsp.h" 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds |xref b1238_fix 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds| 581da177e4SLinus Torvalds| Divide by Zero exception 591da177e4SLinus Torvalds| 601da177e4SLinus Torvalds| All dz exceptions are 'real', hence no fpsp_dz entry point. 611da177e4SLinus Torvalds| 621da177e4SLinus Torvalds .global dz 631da177e4SLinus Torvalds .global real_dz 641da177e4SLinus Torvaldsdz: 651da177e4SLinus Torvaldsreal_dz: 661da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 671da177e4SLinus Torvalds fsave -(%sp) 681da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) 691da177e4SLinus Torvalds frestore (%sp)+ 701da177e4SLinus Torvalds unlk %a6 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds SAVE_ALL_INT 731da177e4SLinus Torvalds GET_CURRENT(%d0) 741da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 751da177e4SLinus Torvalds bsrl trap_c 761da177e4SLinus Torvalds addql #4,%sp 771da177e4SLinus Torvalds bral ret_from_exception 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds| 801da177e4SLinus Torvalds| Inexact exception 811da177e4SLinus Torvalds| 821da177e4SLinus Torvalds| All inexact exceptions are real, but the 'real' handler 831da177e4SLinus Torvalds| will probably want to clear the pending exception. 841da177e4SLinus Torvalds| The provided code will clear the E3 exception (if pending), 851da177e4SLinus Torvalds| otherwise clear the E1 exception. The frestore is not really 861da177e4SLinus Torvalds| necessary for E1 exceptions. 871da177e4SLinus Torvalds| 881da177e4SLinus Torvalds| Code following the 'inex' label is to handle bug #1232. In this 891da177e4SLinus Torvalds| bug, if an E1 snan, ovfl, or unfl occurred, and the process was 901da177e4SLinus Torvalds| swapped out before taking the exception, the exception taken on 911da177e4SLinus Torvalds| return was inex, rather than the correct exception. The snan, ovfl, 921da177e4SLinus Torvalds| and unfl exception to be taken must not have been enabled. The 931da177e4SLinus Torvalds| fix is to check for E1, and the existence of one of snan, ovfl, 941da177e4SLinus Torvalds| or unfl bits set in the fpsr. If any of these are set, branch 951da177e4SLinus Torvalds| to the appropriate handler for the exception in the fpsr. Note 961da177e4SLinus Torvalds| that this fix is only for d43b parts, and is skipped if the 971da177e4SLinus Torvalds| version number is not $40. 981da177e4SLinus Torvalds| 991da177e4SLinus Torvalds| 1001da177e4SLinus Torvalds .global real_inex 1011da177e4SLinus Torvalds .global inex 1021da177e4SLinus Torvaldsinex: 1031da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 1041da177e4SLinus Torvalds fsave -(%sp) 1051da177e4SLinus Torvalds cmpib #VER_40,(%sp) |test version number 1061da177e4SLinus Torvalds bnes not_fmt40 1071da177e4SLinus Torvalds fmovel %fpsr,-(%sp) 1081da177e4SLinus Torvalds btstb #E1,E_BYTE(%a6) |test for E1 set 1091da177e4SLinus Torvalds beqs not_b1232 1101da177e4SLinus Torvalds btstb #snan_bit,2(%sp) |test for snan 1111da177e4SLinus Torvalds beq inex_ckofl 1121da177e4SLinus Torvalds addl #4,%sp 1131da177e4SLinus Torvalds frestore (%sp)+ 1141da177e4SLinus Torvalds unlk %a6 1151da177e4SLinus Torvalds bra snan 1161da177e4SLinus Torvaldsinex_ckofl: 1171da177e4SLinus Torvalds btstb #ovfl_bit,2(%sp) |test for ovfl 1181da177e4SLinus Torvalds beq inex_ckufl 1191da177e4SLinus Torvalds addl #4,%sp 1201da177e4SLinus Torvalds frestore (%sp)+ 1211da177e4SLinus Torvalds unlk %a6 1221da177e4SLinus Torvalds bra ovfl 1231da177e4SLinus Torvaldsinex_ckufl: 1241da177e4SLinus Torvalds btstb #unfl_bit,2(%sp) |test for unfl 1251da177e4SLinus Torvalds beq not_b1232 1261da177e4SLinus Torvalds addl #4,%sp 1271da177e4SLinus Torvalds frestore (%sp)+ 1281da177e4SLinus Torvalds unlk %a6 1291da177e4SLinus Torvalds bra unfl 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds| 1321da177e4SLinus Torvalds| We do not have the bug 1232 case. Clean up the stack and call 1331da177e4SLinus Torvalds| real_inex. 1341da177e4SLinus Torvalds| 1351da177e4SLinus Torvaldsnot_b1232: 1361da177e4SLinus Torvalds addl #4,%sp 1371da177e4SLinus Torvalds frestore (%sp)+ 1381da177e4SLinus Torvalds unlk %a6 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvaldsreal_inex: 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 1431da177e4SLinus Torvalds fsave -(%sp) 1441da177e4SLinus Torvaldsnot_fmt40: 1451da177e4SLinus Torvalds bclrb #E3,E_BYTE(%a6) |clear and test E3 flag 1461da177e4SLinus Torvalds beqs inex_cke1 1471da177e4SLinus Torvalds| 1481da177e4SLinus Torvalds| Clear dirty bit on dest resister in the frame before branching 1491da177e4SLinus Torvalds| to b1238_fix. 1501da177e4SLinus Torvalds| 1511da177e4SLinus Torvalds moveml %d0/%d1,USER_DA(%a6) 1521da177e4SLinus Torvalds bfextu CMDREG1B(%a6){#6:#3},%d0 |get dest reg no 1531da177e4SLinus Torvalds bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit 1541da177e4SLinus Torvalds bsrl b1238_fix |test for bug1238 case 1551da177e4SLinus Torvalds moveml USER_DA(%a6),%d0/%d1 1561da177e4SLinus Torvalds bras inex_done 1571da177e4SLinus Torvaldsinex_cke1: 1581da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) 1591da177e4SLinus Torvaldsinex_done: 1601da177e4SLinus Torvalds frestore (%sp)+ 1611da177e4SLinus Torvalds unlk %a6 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds SAVE_ALL_INT 1641da177e4SLinus Torvalds GET_CURRENT(%d0) 1651da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 1661da177e4SLinus Torvalds bsrl trap_c 1671da177e4SLinus Torvalds addql #4,%sp 1681da177e4SLinus Torvalds bral ret_from_exception 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds| 1711da177e4SLinus Torvalds| Overflow exception 1721da177e4SLinus Torvalds| 1731da177e4SLinus Torvalds |xref fpsp_ovfl 1741da177e4SLinus Torvalds .global real_ovfl 1751da177e4SLinus Torvalds .global ovfl 1761da177e4SLinus Torvaldsovfl: 1771da177e4SLinus Torvalds jmp fpsp_ovfl 1781da177e4SLinus Torvaldsreal_ovfl: 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 1811da177e4SLinus Torvalds fsave -(%sp) 1821da177e4SLinus Torvalds bclrb #E3,E_BYTE(%a6) |clear and test E3 flag 1831da177e4SLinus Torvalds bnes ovfl_done 1841da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) 1851da177e4SLinus Torvaldsovfl_done: 1861da177e4SLinus Torvalds frestore (%sp)+ 1871da177e4SLinus Torvalds unlk %a6 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds SAVE_ALL_INT 1901da177e4SLinus Torvalds GET_CURRENT(%d0) 1911da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 1921da177e4SLinus Torvalds bsrl trap_c 1931da177e4SLinus Torvalds addql #4,%sp 1941da177e4SLinus Torvalds bral ret_from_exception 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds| 1971da177e4SLinus Torvalds| Underflow exception 1981da177e4SLinus Torvalds| 1991da177e4SLinus Torvalds |xref fpsp_unfl 2001da177e4SLinus Torvalds .global real_unfl 2011da177e4SLinus Torvalds .global unfl 2021da177e4SLinus Torvaldsunfl: 2031da177e4SLinus Torvalds jmp fpsp_unfl 2041da177e4SLinus Torvaldsreal_unfl: 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 2071da177e4SLinus Torvalds fsave -(%sp) 2081da177e4SLinus Torvalds bclrb #E3,E_BYTE(%a6) |clear and test E3 flag 2091da177e4SLinus Torvalds bnes unfl_done 2101da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) 2111da177e4SLinus Torvaldsunfl_done: 2121da177e4SLinus Torvalds frestore (%sp)+ 2131da177e4SLinus Torvalds unlk %a6 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds SAVE_ALL_INT 2161da177e4SLinus Torvalds GET_CURRENT(%d0) 2171da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 2181da177e4SLinus Torvalds bsrl trap_c 2191da177e4SLinus Torvalds addql #4,%sp 2201da177e4SLinus Torvalds bral ret_from_exception 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds| 2231da177e4SLinus Torvalds| Signalling NAN exception 2241da177e4SLinus Torvalds| 2251da177e4SLinus Torvalds |xref fpsp_snan 2261da177e4SLinus Torvalds .global real_snan 2271da177e4SLinus Torvalds .global snan 2281da177e4SLinus Torvaldssnan: 2291da177e4SLinus Torvalds jmp fpsp_snan 2301da177e4SLinus Torvaldsreal_snan: 2311da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 2321da177e4SLinus Torvalds fsave -(%sp) 2331da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) |snan is always an E1 exception 2341da177e4SLinus Torvalds frestore (%sp)+ 2351da177e4SLinus Torvalds unlk %a6 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds SAVE_ALL_INT 2381da177e4SLinus Torvalds GET_CURRENT(%d0) 2391da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 2401da177e4SLinus Torvalds bsrl trap_c 2411da177e4SLinus Torvalds addql #4,%sp 2421da177e4SLinus Torvalds bral ret_from_exception 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds| 2451da177e4SLinus Torvalds| Operand Error exception 2461da177e4SLinus Torvalds| 2471da177e4SLinus Torvalds |xref fpsp_operr 2481da177e4SLinus Torvalds .global real_operr 2491da177e4SLinus Torvalds .global operr 2501da177e4SLinus Torvaldsoperr: 2511da177e4SLinus Torvalds jmp fpsp_operr 2521da177e4SLinus Torvaldsreal_operr: 2531da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 2541da177e4SLinus Torvalds fsave -(%sp) 2551da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) |operr is always an E1 exception 2561da177e4SLinus Torvalds frestore (%sp)+ 2571da177e4SLinus Torvalds unlk %a6 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds SAVE_ALL_INT 2601da177e4SLinus Torvalds GET_CURRENT(%d0) 2611da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 2621da177e4SLinus Torvalds bsrl trap_c 2631da177e4SLinus Torvalds addql #4,%sp 2641da177e4SLinus Torvalds bral ret_from_exception 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds| 2681da177e4SLinus Torvalds| BSUN exception 2691da177e4SLinus Torvalds| 2701da177e4SLinus Torvalds| This sample handler simply clears the nan bit in the FPSR. 2711da177e4SLinus Torvalds| 2721da177e4SLinus Torvalds |xref fpsp_bsun 2731da177e4SLinus Torvalds .global real_bsun 2741da177e4SLinus Torvalds .global bsun 2751da177e4SLinus Torvaldsbsun: 2761da177e4SLinus Torvalds jmp fpsp_bsun 2771da177e4SLinus Torvaldsreal_bsun: 2781da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 2791da177e4SLinus Torvalds fsave -(%sp) 2801da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) |bsun is always an E1 exception 2811da177e4SLinus Torvalds fmovel %FPSR,-(%sp) 2821da177e4SLinus Torvalds bclrb #nan_bit,(%sp) 2831da177e4SLinus Torvalds fmovel (%sp)+,%FPSR 2841da177e4SLinus Torvalds frestore (%sp)+ 2851da177e4SLinus Torvalds unlk %a6 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds SAVE_ALL_INT 2881da177e4SLinus Torvalds GET_CURRENT(%d0) 2891da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 2901da177e4SLinus Torvalds bsrl trap_c 2911da177e4SLinus Torvalds addql #4,%sp 2921da177e4SLinus Torvalds bral ret_from_exception 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds| 2951da177e4SLinus Torvalds| F-line exception 2961da177e4SLinus Torvalds| 2971da177e4SLinus Torvalds| A 'real' F-line exception is one that the FPSP isn't supposed to 2981da177e4SLinus Torvalds| handle. E.g. an instruction with a co-processor ID that is not 1. 2991da177e4SLinus Torvalds| 3001da177e4SLinus Torvalds| 3011da177e4SLinus Torvalds |xref fpsp_fline 3021da177e4SLinus Torvalds .global real_fline 3031da177e4SLinus Torvalds .global fline 3041da177e4SLinus Torvaldsfline: 3051da177e4SLinus Torvalds jmp fpsp_fline 3061da177e4SLinus Torvaldsreal_fline: 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds SAVE_ALL_INT 3091da177e4SLinus Torvalds GET_CURRENT(%d0) 3101da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 3111da177e4SLinus Torvalds bsrl trap_c 3121da177e4SLinus Torvalds addql #4,%sp 3131da177e4SLinus Torvalds bral ret_from_exception 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds| 3161da177e4SLinus Torvalds| Unsupported data type exception 3171da177e4SLinus Torvalds| 3181da177e4SLinus Torvalds |xref fpsp_unsupp 3191da177e4SLinus Torvalds .global real_unsupp 3201da177e4SLinus Torvalds .global unsupp 3211da177e4SLinus Torvaldsunsupp: 3221da177e4SLinus Torvalds jmp fpsp_unsupp 3231da177e4SLinus Torvaldsreal_unsupp: 3241da177e4SLinus Torvalds link %a6,#-LOCAL_SIZE 3251da177e4SLinus Torvalds fsave -(%sp) 3261da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) |unsupp is always an E1 exception 3271da177e4SLinus Torvalds frestore (%sp)+ 3281da177e4SLinus Torvalds unlk %a6 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds SAVE_ALL_INT 3311da177e4SLinus Torvalds GET_CURRENT(%d0) 3321da177e4SLinus Torvalds movel %sp,%sp@- | stack frame pointer argument 3331da177e4SLinus Torvalds bsrl trap_c 3341da177e4SLinus Torvalds addql #4,%sp 3351da177e4SLinus Torvalds bral ret_from_exception 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds| 3381da177e4SLinus Torvalds| Trace exception 3391da177e4SLinus Torvalds| 3401da177e4SLinus Torvalds .global real_trace 3411da177e4SLinus Torvaldsreal_trace: 3421da177e4SLinus Torvalds | 3431da177e4SLinus Torvalds bral trap 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds| 3461da177e4SLinus Torvalds| fpsp_fmt_error --- exit point for frame format error 3471da177e4SLinus Torvalds| 3481da177e4SLinus Torvalds| The fpu stack frame does not match the frames existing 3491da177e4SLinus Torvalds| or planned at the time of this writing. The fpsp is 3501da177e4SLinus Torvalds| unable to handle frame sizes not in the following 3511da177e4SLinus Torvalds| version:size pairs: 3521da177e4SLinus Torvalds| 3531da177e4SLinus Torvalds| {4060, 4160} - busy frame 3541da177e4SLinus Torvalds| {4028, 4130} - unimp frame 3551da177e4SLinus Torvalds| {4000, 4100} - idle frame 3561da177e4SLinus Torvalds| 3571da177e4SLinus Torvalds| This entry point simply holds an f-line illegal value. 3581da177e4SLinus Torvalds| Replace this with a call to your kernel panic code or 3591da177e4SLinus Torvalds| code to handle future revisions of the fpu. 3601da177e4SLinus Torvalds| 3611da177e4SLinus Torvalds .global fpsp_fmt_error 3621da177e4SLinus Torvaldsfpsp_fmt_error: 3631da177e4SLinus Torvalds 3641da177e4SLinus Torvalds .long 0xf27f0000 |f-line illegal 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds| 3671da177e4SLinus Torvalds| fpsp_done --- FPSP exit point 3681da177e4SLinus Torvalds| 3691da177e4SLinus Torvalds| The exception has been handled by the package and we are ready 3701da177e4SLinus Torvalds| to return to user mode, but there may be OS specific code 3711da177e4SLinus Torvalds| to execute before we do. If there is, do it now. 3721da177e4SLinus Torvalds| 3731da177e4SLinus Torvalds| 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds .global fpsp_done 3761da177e4SLinus Torvaldsfpsp_done: 3771da177e4SLinus Torvalds btst #0x5,%sp@ | supervisor bit set in saved SR? 3781da177e4SLinus Torvalds beq .Lnotkern 3791da177e4SLinus Torvalds rte 3801da177e4SLinus Torvalds.Lnotkern: 3811da177e4SLinus Torvalds SAVE_ALL_INT 3821da177e4SLinus Torvalds GET_CURRENT(%d0) 3833b66a1edSRoman Zippel | deliver signals, reschedule etc.. 3843b66a1edSRoman Zippel jra ret_from_exception 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds| 3871da177e4SLinus Torvalds| mem_write --- write to user or supervisor address space 3881da177e4SLinus Torvalds| 3891da177e4SLinus Torvalds| Writes to memory while in supervisor mode. copyout accomplishes 3901da177e4SLinus Torvalds| this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function. 3911da177e4SLinus Torvalds| If you don't have copyout, use the local copy of the function below. 3921da177e4SLinus Torvalds| 3931da177e4SLinus Torvalds| a0 - supervisor source address 3941da177e4SLinus Torvalds| a1 - user destination address 3951da177e4SLinus Torvalds| d0 - number of bytes to write (maximum count is 12) 3961da177e4SLinus Torvalds| 3971da177e4SLinus Torvalds| The supervisor source address is guaranteed to point into the supervisor 3981da177e4SLinus Torvalds| stack. The result is that a UNIX 3991da177e4SLinus Torvalds| process is allowed to sleep as a consequence of a page fault during 4001da177e4SLinus Torvalds| copyout. The probability of a page fault is exceedingly small because 4011da177e4SLinus Torvalds| the 68040 always reads the destination address and thus the page 4021da177e4SLinus Torvalds| faults should have already been handled. 4031da177e4SLinus Torvalds| 4041da177e4SLinus Torvalds| If the EXC_SR shows that the exception was from supervisor space, 4051da177e4SLinus Torvalds| then just do a dumb (and slow) memory move. In a UNIX environment 4061da177e4SLinus Torvalds| there shouldn't be any supervisor mode floating point exceptions. 4071da177e4SLinus Torvalds| 4081da177e4SLinus Torvalds .global mem_write 4091da177e4SLinus Torvaldsmem_write: 4101da177e4SLinus Torvalds btstb #5,EXC_SR(%a6) |check for supervisor state 4111da177e4SLinus Torvalds beqs user_write 4121da177e4SLinus Torvaldssuper_write: 4131da177e4SLinus Torvalds moveb (%a0)+,(%a1)+ 4141da177e4SLinus Torvalds subql #1,%d0 4151da177e4SLinus Torvalds bnes super_write 4161da177e4SLinus Torvalds rts 4171da177e4SLinus Torvaldsuser_write: 4181da177e4SLinus Torvalds movel %d1,-(%sp) |preserve d1 just in case 4191da177e4SLinus Torvalds movel %d0,-(%sp) 4201da177e4SLinus Torvalds movel %a1,-(%sp) 4211da177e4SLinus Torvalds movel %a0,-(%sp) 4221da177e4SLinus Torvalds jsr copyout 4231da177e4SLinus Torvalds addw #12,%sp 4241da177e4SLinus Torvalds movel (%sp)+,%d1 4251da177e4SLinus Torvalds rts 4261da177e4SLinus Torvalds| 4271da177e4SLinus Torvalds| mem_read --- read from user or supervisor address space 4281da177e4SLinus Torvalds| 4291da177e4SLinus Torvalds| Reads from memory while in supervisor mode. copyin accomplishes 4301da177e4SLinus Torvalds| this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function. 4311da177e4SLinus Torvalds| If you don't have copyin, use the local copy of the function below. 4321da177e4SLinus Torvalds| 4331da177e4SLinus Torvalds| The FPSP calls mem_read to read the original F-line instruction in order 4341da177e4SLinus Torvalds| to extract the data register number when the 'Dn' addressing mode is 4351da177e4SLinus Torvalds| used. 4361da177e4SLinus Torvalds| 4371da177e4SLinus Torvalds|Input: 4381da177e4SLinus Torvalds| a0 - user source address 4391da177e4SLinus Torvalds| a1 - supervisor destination address 4401da177e4SLinus Torvalds| d0 - number of bytes to read (maximum count is 12) 4411da177e4SLinus Torvalds| 4421da177e4SLinus Torvalds| Like mem_write, mem_read always reads with a supervisor 4431da177e4SLinus Torvalds| destination address on the supervisor stack. Also like mem_write, 4441da177e4SLinus Torvalds| the EXC_SR is checked and a simple memory copy is done if reading 4451da177e4SLinus Torvalds| from supervisor space is indicated. 4461da177e4SLinus Torvalds| 4471da177e4SLinus Torvalds .global mem_read 4481da177e4SLinus Torvaldsmem_read: 4491da177e4SLinus Torvalds btstb #5,EXC_SR(%a6) |check for supervisor state 4501da177e4SLinus Torvalds beqs user_read 4511da177e4SLinus Torvaldssuper_read: 4521da177e4SLinus Torvalds moveb (%a0)+,(%a1)+ 4531da177e4SLinus Torvalds subql #1,%d0 4541da177e4SLinus Torvalds bnes super_read 4551da177e4SLinus Torvalds rts 4561da177e4SLinus Torvaldsuser_read: 4571da177e4SLinus Torvalds movel %d1,-(%sp) |preserve d1 just in case 4581da177e4SLinus Torvalds movel %d0,-(%sp) 4591da177e4SLinus Torvalds movel %a1,-(%sp) 4601da177e4SLinus Torvalds movel %a0,-(%sp) 4611da177e4SLinus Torvalds jsr copyin 4621da177e4SLinus Torvalds addw #12,%sp 4631da177e4SLinus Torvalds movel (%sp)+,%d1 4641da177e4SLinus Torvalds rts 4651da177e4SLinus Torvalds 4661da177e4SLinus Torvalds| 4671da177e4SLinus Torvalds| Use these routines if your kernel doesn't have copyout/copyin equivalents. 4681da177e4SLinus Torvalds| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC, 4691da177e4SLinus Torvalds| and copyin overwrites SFC. 4701da177e4SLinus Torvalds| 4711da177e4SLinus Torvaldscopyout: 4721da177e4SLinus Torvalds movel 4(%sp),%a0 | source 4731da177e4SLinus Torvalds movel 8(%sp),%a1 | destination 4741da177e4SLinus Torvalds movel 12(%sp),%d0 | count 4751da177e4SLinus Torvalds subl #1,%d0 | dec count by 1 for dbra 4761da177e4SLinus Torvalds movel #1,%d1 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds| DFC is already set 4791da177e4SLinus Torvalds| movec %d1,%DFC | set dfc for user data space 4801da177e4SLinus Torvaldsmoreout: 4811da177e4SLinus Torvalds moveb (%a0)+,%d1 | fetch supervisor byte 4821da177e4SLinus Torvaldsout_ea: 4831da177e4SLinus Torvalds movesb %d1,(%a1)+ | write user byte 4841da177e4SLinus Torvalds dbf %d0,moreout 4851da177e4SLinus Torvalds rts 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvaldscopyin: 4881da177e4SLinus Torvalds movel 4(%sp),%a0 | source 4891da177e4SLinus Torvalds movel 8(%sp),%a1 | destination 4901da177e4SLinus Torvalds movel 12(%sp),%d0 | count 4911da177e4SLinus Torvalds subl #1,%d0 | dec count by 1 for dbra 4921da177e4SLinus Torvalds movel #1,%d1 4931da177e4SLinus Torvalds| SFC is already set 4941da177e4SLinus Torvalds| movec %d1,%SFC | set sfc for user space 4951da177e4SLinus Torvaldsmorein: 4961da177e4SLinus Torvaldsin_ea: 4971da177e4SLinus Torvalds movesb (%a0)+,%d1 | fetch user byte 4981da177e4SLinus Torvalds moveb %d1,(%a1)+ | write supervisor byte 4991da177e4SLinus Torvalds dbf %d0,morein 5001da177e4SLinus Torvalds rts 5011da177e4SLinus Torvalds 502*922a9bd1SBen Hutchings .section .fixup,"ax" 5031da177e4SLinus Torvalds .even 5041da177e4SLinus Torvalds1: 505a3616a3cSEric W. Biederman jbsr fpsp040_die 506a3616a3cSEric W. Biederman jbra .Lnotkern 5071da177e4SLinus Torvalds 508*922a9bd1SBen Hutchings .section __ex_table,"a" 5091da177e4SLinus Torvalds .align 4 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds .long in_ea,1b 5121da177e4SLinus Torvalds .long out_ea,1b 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds |end 515