162306a36Sopenharmony_ci| 262306a36Sopenharmony_ci| skeleton.sa 3.2 4/26/91 362306a36Sopenharmony_ci| 462306a36Sopenharmony_ci| This file contains code that is system dependent and will 562306a36Sopenharmony_ci| need to be modified to install the FPSP. 662306a36Sopenharmony_ci| 762306a36Sopenharmony_ci| Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'. 862306a36Sopenharmony_ci| Put any target system specific handling that must be done immediately 962306a36Sopenharmony_ci| before the jump instruction. If there no handling necessary, then 1062306a36Sopenharmony_ci| the 'fpsp_xxxx' handler entry point should be placed in the exception 1162306a36Sopenharmony_ci| table so that the 'jmp' can be eliminated. If the FPSP determines that the 1262306a36Sopenharmony_ci| exception is one that must be reported then there will be a 1362306a36Sopenharmony_ci| return from the package by a 'jmp real_xxxx'. At that point 1462306a36Sopenharmony_ci| the machine state will be identical to the state before 1562306a36Sopenharmony_ci| the FPSP was entered. In particular, whatever condition 1662306a36Sopenharmony_ci| that caused the exception will still be pending when the FPSP 1762306a36Sopenharmony_ci| package returns. Thus, there will be system specific code 1862306a36Sopenharmony_ci| to handle the exception. 1962306a36Sopenharmony_ci| 2062306a36Sopenharmony_ci| If the exception was completely handled by the package, then 2162306a36Sopenharmony_ci| the return will be via a 'jmp fpsp_done'. Unless there is 2262306a36Sopenharmony_ci| OS specific work to be done (such as handling a context switch or 2362306a36Sopenharmony_ci| interrupt) the user program can be resumed via 'rte'. 2462306a36Sopenharmony_ci| 2562306a36Sopenharmony_ci| In the following skeleton code, some typical 'real_xxxx' handling 2662306a36Sopenharmony_ci| code is shown. This code may need to be moved to an appropriate 2762306a36Sopenharmony_ci| place in the target system, or rewritten. 2862306a36Sopenharmony_ci| 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 3162306a36Sopenharmony_ci| All Rights Reserved 3262306a36Sopenharmony_ci| 3362306a36Sopenharmony_ci| For details on the license for this file, please see the 3462306a36Sopenharmony_ci| file, README, in this same directory. 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci| 3762306a36Sopenharmony_ci| Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk) 3862306a36Sopenharmony_ci| 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include <linux/linkage.h> 4162306a36Sopenharmony_ci#include <asm/entry.h> 4262306a36Sopenharmony_ci#include <asm/asm-offsets.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci|SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci |section 15 4762306a36Sopenharmony_ci| 4862306a36Sopenharmony_ci| The following counters are used for standalone testing 4962306a36Sopenharmony_ci| 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci |section 8 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#include "fpsp.h" 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci |xref b1238_fix 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci| 5862306a36Sopenharmony_ci| Divide by Zero exception 5962306a36Sopenharmony_ci| 6062306a36Sopenharmony_ci| All dz exceptions are 'real', hence no fpsp_dz entry point. 6162306a36Sopenharmony_ci| 6262306a36Sopenharmony_ci .global dz 6362306a36Sopenharmony_ci .global real_dz 6462306a36Sopenharmony_cidz: 6562306a36Sopenharmony_cireal_dz: 6662306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 6762306a36Sopenharmony_ci fsave -(%sp) 6862306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 6962306a36Sopenharmony_ci frestore (%sp)+ 7062306a36Sopenharmony_ci unlk %a6 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci SAVE_ALL_INT 7362306a36Sopenharmony_ci GET_CURRENT(%d0) 7462306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 7562306a36Sopenharmony_ci bsrl trap_c 7662306a36Sopenharmony_ci addql #4,%sp 7762306a36Sopenharmony_ci bral ret_from_exception 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci| 8062306a36Sopenharmony_ci| Inexact exception 8162306a36Sopenharmony_ci| 8262306a36Sopenharmony_ci| All inexact exceptions are real, but the 'real' handler 8362306a36Sopenharmony_ci| will probably want to clear the pending exception. 8462306a36Sopenharmony_ci| The provided code will clear the E3 exception (if pending), 8562306a36Sopenharmony_ci| otherwise clear the E1 exception. The frestore is not really 8662306a36Sopenharmony_ci| necessary for E1 exceptions. 8762306a36Sopenharmony_ci| 8862306a36Sopenharmony_ci| Code following the 'inex' label is to handle bug #1232. In this 8962306a36Sopenharmony_ci| bug, if an E1 snan, ovfl, or unfl occurred, and the process was 9062306a36Sopenharmony_ci| swapped out before taking the exception, the exception taken on 9162306a36Sopenharmony_ci| return was inex, rather than the correct exception. The snan, ovfl, 9262306a36Sopenharmony_ci| and unfl exception to be taken must not have been enabled. The 9362306a36Sopenharmony_ci| fix is to check for E1, and the existence of one of snan, ovfl, 9462306a36Sopenharmony_ci| or unfl bits set in the fpsr. If any of these are set, branch 9562306a36Sopenharmony_ci| to the appropriate handler for the exception in the fpsr. Note 9662306a36Sopenharmony_ci| that this fix is only for d43b parts, and is skipped if the 9762306a36Sopenharmony_ci| version number is not $40. 9862306a36Sopenharmony_ci| 9962306a36Sopenharmony_ci| 10062306a36Sopenharmony_ci .global real_inex 10162306a36Sopenharmony_ci .global inex 10262306a36Sopenharmony_ciinex: 10362306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 10462306a36Sopenharmony_ci fsave -(%sp) 10562306a36Sopenharmony_ci cmpib #VER_40,(%sp) |test version number 10662306a36Sopenharmony_ci bnes not_fmt40 10762306a36Sopenharmony_ci fmovel %fpsr,-(%sp) 10862306a36Sopenharmony_ci btstb #E1,E_BYTE(%a6) |test for E1 set 10962306a36Sopenharmony_ci beqs not_b1232 11062306a36Sopenharmony_ci btstb #snan_bit,2(%sp) |test for snan 11162306a36Sopenharmony_ci beq inex_ckofl 11262306a36Sopenharmony_ci addl #4,%sp 11362306a36Sopenharmony_ci frestore (%sp)+ 11462306a36Sopenharmony_ci unlk %a6 11562306a36Sopenharmony_ci bra snan 11662306a36Sopenharmony_ciinex_ckofl: 11762306a36Sopenharmony_ci btstb #ovfl_bit,2(%sp) |test for ovfl 11862306a36Sopenharmony_ci beq inex_ckufl 11962306a36Sopenharmony_ci addl #4,%sp 12062306a36Sopenharmony_ci frestore (%sp)+ 12162306a36Sopenharmony_ci unlk %a6 12262306a36Sopenharmony_ci bra ovfl 12362306a36Sopenharmony_ciinex_ckufl: 12462306a36Sopenharmony_ci btstb #unfl_bit,2(%sp) |test for unfl 12562306a36Sopenharmony_ci beq not_b1232 12662306a36Sopenharmony_ci addl #4,%sp 12762306a36Sopenharmony_ci frestore (%sp)+ 12862306a36Sopenharmony_ci unlk %a6 12962306a36Sopenharmony_ci bra unfl 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci| 13262306a36Sopenharmony_ci| We do not have the bug 1232 case. Clean up the stack and call 13362306a36Sopenharmony_ci| real_inex. 13462306a36Sopenharmony_ci| 13562306a36Sopenharmony_cinot_b1232: 13662306a36Sopenharmony_ci addl #4,%sp 13762306a36Sopenharmony_ci frestore (%sp)+ 13862306a36Sopenharmony_ci unlk %a6 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cireal_inex: 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 14362306a36Sopenharmony_ci fsave -(%sp) 14462306a36Sopenharmony_cinot_fmt40: 14562306a36Sopenharmony_ci bclrb #E3,E_BYTE(%a6) |clear and test E3 flag 14662306a36Sopenharmony_ci beqs inex_cke1 14762306a36Sopenharmony_ci| 14862306a36Sopenharmony_ci| Clear dirty bit on dest resister in the frame before branching 14962306a36Sopenharmony_ci| to b1238_fix. 15062306a36Sopenharmony_ci| 15162306a36Sopenharmony_ci moveml %d0/%d1,USER_DA(%a6) 15262306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#6:#3},%d0 |get dest reg no 15362306a36Sopenharmony_ci bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit 15462306a36Sopenharmony_ci bsrl b1238_fix |test for bug1238 case 15562306a36Sopenharmony_ci moveml USER_DA(%a6),%d0/%d1 15662306a36Sopenharmony_ci bras inex_done 15762306a36Sopenharmony_ciinex_cke1: 15862306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 15962306a36Sopenharmony_ciinex_done: 16062306a36Sopenharmony_ci frestore (%sp)+ 16162306a36Sopenharmony_ci unlk %a6 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci SAVE_ALL_INT 16462306a36Sopenharmony_ci GET_CURRENT(%d0) 16562306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 16662306a36Sopenharmony_ci bsrl trap_c 16762306a36Sopenharmony_ci addql #4,%sp 16862306a36Sopenharmony_ci bral ret_from_exception 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci| 17162306a36Sopenharmony_ci| Overflow exception 17262306a36Sopenharmony_ci| 17362306a36Sopenharmony_ci |xref fpsp_ovfl 17462306a36Sopenharmony_ci .global real_ovfl 17562306a36Sopenharmony_ci .global ovfl 17662306a36Sopenharmony_ciovfl: 17762306a36Sopenharmony_ci jmp fpsp_ovfl 17862306a36Sopenharmony_cireal_ovfl: 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 18162306a36Sopenharmony_ci fsave -(%sp) 18262306a36Sopenharmony_ci bclrb #E3,E_BYTE(%a6) |clear and test E3 flag 18362306a36Sopenharmony_ci bnes ovfl_done 18462306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 18562306a36Sopenharmony_ciovfl_done: 18662306a36Sopenharmony_ci frestore (%sp)+ 18762306a36Sopenharmony_ci unlk %a6 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci SAVE_ALL_INT 19062306a36Sopenharmony_ci GET_CURRENT(%d0) 19162306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 19262306a36Sopenharmony_ci bsrl trap_c 19362306a36Sopenharmony_ci addql #4,%sp 19462306a36Sopenharmony_ci bral ret_from_exception 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci| 19762306a36Sopenharmony_ci| Underflow exception 19862306a36Sopenharmony_ci| 19962306a36Sopenharmony_ci |xref fpsp_unfl 20062306a36Sopenharmony_ci .global real_unfl 20162306a36Sopenharmony_ci .global unfl 20262306a36Sopenharmony_ciunfl: 20362306a36Sopenharmony_ci jmp fpsp_unfl 20462306a36Sopenharmony_cireal_unfl: 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 20762306a36Sopenharmony_ci fsave -(%sp) 20862306a36Sopenharmony_ci bclrb #E3,E_BYTE(%a6) |clear and test E3 flag 20962306a36Sopenharmony_ci bnes unfl_done 21062306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 21162306a36Sopenharmony_ciunfl_done: 21262306a36Sopenharmony_ci frestore (%sp)+ 21362306a36Sopenharmony_ci unlk %a6 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci SAVE_ALL_INT 21662306a36Sopenharmony_ci GET_CURRENT(%d0) 21762306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 21862306a36Sopenharmony_ci bsrl trap_c 21962306a36Sopenharmony_ci addql #4,%sp 22062306a36Sopenharmony_ci bral ret_from_exception 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci| 22362306a36Sopenharmony_ci| Signalling NAN exception 22462306a36Sopenharmony_ci| 22562306a36Sopenharmony_ci |xref fpsp_snan 22662306a36Sopenharmony_ci .global real_snan 22762306a36Sopenharmony_ci .global snan 22862306a36Sopenharmony_cisnan: 22962306a36Sopenharmony_ci jmp fpsp_snan 23062306a36Sopenharmony_cireal_snan: 23162306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 23262306a36Sopenharmony_ci fsave -(%sp) 23362306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |snan is always an E1 exception 23462306a36Sopenharmony_ci frestore (%sp)+ 23562306a36Sopenharmony_ci unlk %a6 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci SAVE_ALL_INT 23862306a36Sopenharmony_ci GET_CURRENT(%d0) 23962306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 24062306a36Sopenharmony_ci bsrl trap_c 24162306a36Sopenharmony_ci addql #4,%sp 24262306a36Sopenharmony_ci bral ret_from_exception 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci| 24562306a36Sopenharmony_ci| Operand Error exception 24662306a36Sopenharmony_ci| 24762306a36Sopenharmony_ci |xref fpsp_operr 24862306a36Sopenharmony_ci .global real_operr 24962306a36Sopenharmony_ci .global operr 25062306a36Sopenharmony_cioperr: 25162306a36Sopenharmony_ci jmp fpsp_operr 25262306a36Sopenharmony_cireal_operr: 25362306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 25462306a36Sopenharmony_ci fsave -(%sp) 25562306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |operr is always an E1 exception 25662306a36Sopenharmony_ci frestore (%sp)+ 25762306a36Sopenharmony_ci unlk %a6 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci SAVE_ALL_INT 26062306a36Sopenharmony_ci GET_CURRENT(%d0) 26162306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 26262306a36Sopenharmony_ci bsrl trap_c 26362306a36Sopenharmony_ci addql #4,%sp 26462306a36Sopenharmony_ci bral ret_from_exception 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci| 26862306a36Sopenharmony_ci| BSUN exception 26962306a36Sopenharmony_ci| 27062306a36Sopenharmony_ci| This sample handler simply clears the nan bit in the FPSR. 27162306a36Sopenharmony_ci| 27262306a36Sopenharmony_ci |xref fpsp_bsun 27362306a36Sopenharmony_ci .global real_bsun 27462306a36Sopenharmony_ci .global bsun 27562306a36Sopenharmony_cibsun: 27662306a36Sopenharmony_ci jmp fpsp_bsun 27762306a36Sopenharmony_cireal_bsun: 27862306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 27962306a36Sopenharmony_ci fsave -(%sp) 28062306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |bsun is always an E1 exception 28162306a36Sopenharmony_ci fmovel %FPSR,-(%sp) 28262306a36Sopenharmony_ci bclrb #nan_bit,(%sp) 28362306a36Sopenharmony_ci fmovel (%sp)+,%FPSR 28462306a36Sopenharmony_ci frestore (%sp)+ 28562306a36Sopenharmony_ci unlk %a6 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci SAVE_ALL_INT 28862306a36Sopenharmony_ci GET_CURRENT(%d0) 28962306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 29062306a36Sopenharmony_ci bsrl trap_c 29162306a36Sopenharmony_ci addql #4,%sp 29262306a36Sopenharmony_ci bral ret_from_exception 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci| 29562306a36Sopenharmony_ci| F-line exception 29662306a36Sopenharmony_ci| 29762306a36Sopenharmony_ci| A 'real' F-line exception is one that the FPSP isn't supposed to 29862306a36Sopenharmony_ci| handle. E.g. an instruction with a co-processor ID that is not 1. 29962306a36Sopenharmony_ci| 30062306a36Sopenharmony_ci| 30162306a36Sopenharmony_ci |xref fpsp_fline 30262306a36Sopenharmony_ci .global real_fline 30362306a36Sopenharmony_ci .global fline 30462306a36Sopenharmony_cifline: 30562306a36Sopenharmony_ci jmp fpsp_fline 30662306a36Sopenharmony_cireal_fline: 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci SAVE_ALL_INT 30962306a36Sopenharmony_ci GET_CURRENT(%d0) 31062306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 31162306a36Sopenharmony_ci bsrl trap_c 31262306a36Sopenharmony_ci addql #4,%sp 31362306a36Sopenharmony_ci bral ret_from_exception 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci| 31662306a36Sopenharmony_ci| Unsupported data type exception 31762306a36Sopenharmony_ci| 31862306a36Sopenharmony_ci |xref fpsp_unsupp 31962306a36Sopenharmony_ci .global real_unsupp 32062306a36Sopenharmony_ci .global unsupp 32162306a36Sopenharmony_ciunsupp: 32262306a36Sopenharmony_ci jmp fpsp_unsupp 32362306a36Sopenharmony_cireal_unsupp: 32462306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 32562306a36Sopenharmony_ci fsave -(%sp) 32662306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |unsupp is always an E1 exception 32762306a36Sopenharmony_ci frestore (%sp)+ 32862306a36Sopenharmony_ci unlk %a6 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci SAVE_ALL_INT 33162306a36Sopenharmony_ci GET_CURRENT(%d0) 33262306a36Sopenharmony_ci movel %sp,%sp@- | stack frame pointer argument 33362306a36Sopenharmony_ci bsrl trap_c 33462306a36Sopenharmony_ci addql #4,%sp 33562306a36Sopenharmony_ci bral ret_from_exception 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci| 33862306a36Sopenharmony_ci| Trace exception 33962306a36Sopenharmony_ci| 34062306a36Sopenharmony_ci .global real_trace 34162306a36Sopenharmony_cireal_trace: 34262306a36Sopenharmony_ci | 34362306a36Sopenharmony_ci bral trap 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci| 34662306a36Sopenharmony_ci| fpsp_fmt_error --- exit point for frame format error 34762306a36Sopenharmony_ci| 34862306a36Sopenharmony_ci| The fpu stack frame does not match the frames existing 34962306a36Sopenharmony_ci| or planned at the time of this writing. The fpsp is 35062306a36Sopenharmony_ci| unable to handle frame sizes not in the following 35162306a36Sopenharmony_ci| version:size pairs: 35262306a36Sopenharmony_ci| 35362306a36Sopenharmony_ci| {4060, 4160} - busy frame 35462306a36Sopenharmony_ci| {4028, 4130} - unimp frame 35562306a36Sopenharmony_ci| {4000, 4100} - idle frame 35662306a36Sopenharmony_ci| 35762306a36Sopenharmony_ci| This entry point simply holds an f-line illegal value. 35862306a36Sopenharmony_ci| Replace this with a call to your kernel panic code or 35962306a36Sopenharmony_ci| code to handle future revisions of the fpu. 36062306a36Sopenharmony_ci| 36162306a36Sopenharmony_ci .global fpsp_fmt_error 36262306a36Sopenharmony_cifpsp_fmt_error: 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci .long 0xf27f0000 |f-line illegal 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci| 36762306a36Sopenharmony_ci| fpsp_done --- FPSP exit point 36862306a36Sopenharmony_ci| 36962306a36Sopenharmony_ci| The exception has been handled by the package and we are ready 37062306a36Sopenharmony_ci| to return to user mode, but there may be OS specific code 37162306a36Sopenharmony_ci| to execute before we do. If there is, do it now. 37262306a36Sopenharmony_ci| 37362306a36Sopenharmony_ci| 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci .global fpsp_done 37662306a36Sopenharmony_cifpsp_done: 37762306a36Sopenharmony_ci btst #0x5,%sp@ | supervisor bit set in saved SR? 37862306a36Sopenharmony_ci beq .Lnotkern 37962306a36Sopenharmony_ci rte 38062306a36Sopenharmony_ci.Lnotkern: 38162306a36Sopenharmony_ci SAVE_ALL_INT 38262306a36Sopenharmony_ci GET_CURRENT(%d0) 38362306a36Sopenharmony_ci | deliver signals, reschedule etc.. 38462306a36Sopenharmony_ci jra ret_from_exception 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci| 38762306a36Sopenharmony_ci| mem_write --- write to user or supervisor address space 38862306a36Sopenharmony_ci| 38962306a36Sopenharmony_ci| Writes to memory while in supervisor mode. copyout accomplishes 39062306a36Sopenharmony_ci| this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function. 39162306a36Sopenharmony_ci| If you don't have copyout, use the local copy of the function below. 39262306a36Sopenharmony_ci| 39362306a36Sopenharmony_ci| a0 - supervisor source address 39462306a36Sopenharmony_ci| a1 - user destination address 39562306a36Sopenharmony_ci| d0 - number of bytes to write (maximum count is 12) 39662306a36Sopenharmony_ci| 39762306a36Sopenharmony_ci| The supervisor source address is guaranteed to point into the supervisor 39862306a36Sopenharmony_ci| stack. The result is that a UNIX 39962306a36Sopenharmony_ci| process is allowed to sleep as a consequence of a page fault during 40062306a36Sopenharmony_ci| copyout. The probability of a page fault is exceedingly small because 40162306a36Sopenharmony_ci| the 68040 always reads the destination address and thus the page 40262306a36Sopenharmony_ci| faults should have already been handled. 40362306a36Sopenharmony_ci| 40462306a36Sopenharmony_ci| If the EXC_SR shows that the exception was from supervisor space, 40562306a36Sopenharmony_ci| then just do a dumb (and slow) memory move. In a UNIX environment 40662306a36Sopenharmony_ci| there shouldn't be any supervisor mode floating point exceptions. 40762306a36Sopenharmony_ci| 40862306a36Sopenharmony_ci .global mem_write 40962306a36Sopenharmony_cimem_write: 41062306a36Sopenharmony_ci btstb #5,EXC_SR(%a6) |check for supervisor state 41162306a36Sopenharmony_ci beqs user_write 41262306a36Sopenharmony_cisuper_write: 41362306a36Sopenharmony_ci moveb (%a0)+,(%a1)+ 41462306a36Sopenharmony_ci subql #1,%d0 41562306a36Sopenharmony_ci bnes super_write 41662306a36Sopenharmony_ci rts 41762306a36Sopenharmony_ciuser_write: 41862306a36Sopenharmony_ci movel %d1,-(%sp) |preserve d1 just in case 41962306a36Sopenharmony_ci movel %d0,-(%sp) 42062306a36Sopenharmony_ci movel %a1,-(%sp) 42162306a36Sopenharmony_ci movel %a0,-(%sp) 42262306a36Sopenharmony_ci jsr copyout 42362306a36Sopenharmony_ci addw #12,%sp 42462306a36Sopenharmony_ci movel (%sp)+,%d1 42562306a36Sopenharmony_ci rts 42662306a36Sopenharmony_ci| 42762306a36Sopenharmony_ci| mem_read --- read from user or supervisor address space 42862306a36Sopenharmony_ci| 42962306a36Sopenharmony_ci| Reads from memory while in supervisor mode. copyin accomplishes 43062306a36Sopenharmony_ci| this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function. 43162306a36Sopenharmony_ci| If you don't have copyin, use the local copy of the function below. 43262306a36Sopenharmony_ci| 43362306a36Sopenharmony_ci| The FPSP calls mem_read to read the original F-line instruction in order 43462306a36Sopenharmony_ci| to extract the data register number when the 'Dn' addressing mode is 43562306a36Sopenharmony_ci| used. 43662306a36Sopenharmony_ci| 43762306a36Sopenharmony_ci|Input: 43862306a36Sopenharmony_ci| a0 - user source address 43962306a36Sopenharmony_ci| a1 - supervisor destination address 44062306a36Sopenharmony_ci| d0 - number of bytes to read (maximum count is 12) 44162306a36Sopenharmony_ci| 44262306a36Sopenharmony_ci| Like mem_write, mem_read always reads with a supervisor 44362306a36Sopenharmony_ci| destination address on the supervisor stack. Also like mem_write, 44462306a36Sopenharmony_ci| the EXC_SR is checked and a simple memory copy is done if reading 44562306a36Sopenharmony_ci| from supervisor space is indicated. 44662306a36Sopenharmony_ci| 44762306a36Sopenharmony_ci .global mem_read 44862306a36Sopenharmony_cimem_read: 44962306a36Sopenharmony_ci btstb #5,EXC_SR(%a6) |check for supervisor state 45062306a36Sopenharmony_ci beqs user_read 45162306a36Sopenharmony_cisuper_read: 45262306a36Sopenharmony_ci moveb (%a0)+,(%a1)+ 45362306a36Sopenharmony_ci subql #1,%d0 45462306a36Sopenharmony_ci bnes super_read 45562306a36Sopenharmony_ci rts 45662306a36Sopenharmony_ciuser_read: 45762306a36Sopenharmony_ci movel %d1,-(%sp) |preserve d1 just in case 45862306a36Sopenharmony_ci movel %d0,-(%sp) 45962306a36Sopenharmony_ci movel %a1,-(%sp) 46062306a36Sopenharmony_ci movel %a0,-(%sp) 46162306a36Sopenharmony_ci jsr copyin 46262306a36Sopenharmony_ci addw #12,%sp 46362306a36Sopenharmony_ci movel (%sp)+,%d1 46462306a36Sopenharmony_ci rts 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci| 46762306a36Sopenharmony_ci| Use these routines if your kernel doesn't have copyout/copyin equivalents. 46862306a36Sopenharmony_ci| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC, 46962306a36Sopenharmony_ci| and copyin overwrites SFC. 47062306a36Sopenharmony_ci| 47162306a36Sopenharmony_cicopyout: 47262306a36Sopenharmony_ci movel 4(%sp),%a0 | source 47362306a36Sopenharmony_ci movel 8(%sp),%a1 | destination 47462306a36Sopenharmony_ci movel 12(%sp),%d0 | count 47562306a36Sopenharmony_ci subl #1,%d0 | dec count by 1 for dbra 47662306a36Sopenharmony_ci movel #1,%d1 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci| DFC is already set 47962306a36Sopenharmony_ci| movec %d1,%DFC | set dfc for user data space 48062306a36Sopenharmony_cimoreout: 48162306a36Sopenharmony_ci moveb (%a0)+,%d1 | fetch supervisor byte 48262306a36Sopenharmony_ciout_ea: 48362306a36Sopenharmony_ci movesb %d1,(%a1)+ | write user byte 48462306a36Sopenharmony_ci dbf %d0,moreout 48562306a36Sopenharmony_ci rts 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cicopyin: 48862306a36Sopenharmony_ci movel 4(%sp),%a0 | source 48962306a36Sopenharmony_ci movel 8(%sp),%a1 | destination 49062306a36Sopenharmony_ci movel 12(%sp),%d0 | count 49162306a36Sopenharmony_ci subl #1,%d0 | dec count by 1 for dbra 49262306a36Sopenharmony_ci movel #1,%d1 49362306a36Sopenharmony_ci| SFC is already set 49462306a36Sopenharmony_ci| movec %d1,%SFC | set sfc for user space 49562306a36Sopenharmony_cimorein: 49662306a36Sopenharmony_ciin_ea: 49762306a36Sopenharmony_ci movesb (%a0)+,%d1 | fetch user byte 49862306a36Sopenharmony_ci moveb %d1,(%a1)+ | write supervisor byte 49962306a36Sopenharmony_ci dbf %d0,morein 50062306a36Sopenharmony_ci rts 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci .section .fixup,"ax" 50362306a36Sopenharmony_ci .even 50462306a36Sopenharmony_ci1: 50562306a36Sopenharmony_ci jbsr fpsp040_die 50662306a36Sopenharmony_ci jbra .Lnotkern 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci .section __ex_table,"a" 50962306a36Sopenharmony_ci .align 4 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci .long in_ea,1b 51262306a36Sopenharmony_ci .long out_ea,1b 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci |end 515