162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * fp_emu.S 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright Roman Zippel, 1997. All rights reserved. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 762306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 862306a36Sopenharmony_ci * are met: 962306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1062306a36Sopenharmony_ci * notice, and the entire permission notice in its entirety, 1162306a36Sopenharmony_ci * including the disclaimer of warranties. 1262306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 1362306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 1462306a36Sopenharmony_ci * documentation and/or other materials provided with the distribution. 1562306a36Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote 1662306a36Sopenharmony_ci * products derived from this software without specific prior 1762306a36Sopenharmony_ci * written permission. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of 2062306a36Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL are 2162306a36Sopenharmony_ci * required INSTEAD OF the above restrictions. (This clause is 2262306a36Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and 2362306a36Sopenharmony_ci * the restrictions contained in a BSD-style copyright.) 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 2662306a36Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2762306a36Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2862306a36Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2962306a36Sopenharmony_ci * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3062306a36Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3162306a36Sopenharmony_ci * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3262306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3362306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3462306a36Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 3562306a36Sopenharmony_ci * OF THE POSSIBILITY OF SUCH DAMAGE. 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include <linux/linkage.h> 3962306a36Sopenharmony_ci#include <asm/entry.h> 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include "fp_emu.h" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci .globl fpu_emu 4462306a36Sopenharmony_ci .globl fp_debugprint 4562306a36Sopenharmony_ci .globl fp_err_ua1,fp_err_ua2 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci .text 4862306a36Sopenharmony_cifpu_emu: 4962306a36Sopenharmony_ci SAVE_ALL_INT 5062306a36Sopenharmony_ci GET_CURRENT(%d0) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) 5362306a36Sopenharmony_ci tst.l m68k_is040or060 5462306a36Sopenharmony_ci jeq 1f 5562306a36Sopenharmony_ci#endif 5662306a36Sopenharmony_ci#if defined(CPU_M68040_OR_M68060) 5762306a36Sopenharmony_ci move.l (FPS_PC2,%sp),(FPS_PC,%sp) 5862306a36Sopenharmony_ci#endif 5962306a36Sopenharmony_ci1: 6062306a36Sopenharmony_ci | emulate the instruction 6162306a36Sopenharmony_ci jsr fp_scan 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#if defined(CONFIG_M68060) 6462306a36Sopenharmony_ci#if !defined(CPU_M68060_ONLY) 6562306a36Sopenharmony_ci btst #3,m68k_cputype+3 6662306a36Sopenharmony_ci jeq 1f 6762306a36Sopenharmony_ci#endif 6862306a36Sopenharmony_ci btst #7,(FPS_SR,%sp) 6962306a36Sopenharmony_ci jne fp_sendtrace060 7062306a36Sopenharmony_ci#endif 7162306a36Sopenharmony_ci1: 7262306a36Sopenharmony_ci | emulation successful? 7362306a36Sopenharmony_ci tst.l %d0 7462306a36Sopenharmony_ci jeq ret_from_exception 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci | send some signal to program here 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci jra ret_from_exception 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci | we jump here after an access error while trying to access 8162306a36Sopenharmony_ci | user space, we correct stackpointer and send a SIGSEGV to 8262306a36Sopenharmony_ci | the user process 8362306a36Sopenharmony_cifp_err_ua2: 8462306a36Sopenharmony_ci addq.l #4,%sp 8562306a36Sopenharmony_cifp_err_ua1: 8662306a36Sopenharmony_ci addq.l #4,%sp 8762306a36Sopenharmony_ci move.l %a0,-(%sp) 8862306a36Sopenharmony_ci pea LSEGV_MAPERR 8962306a36Sopenharmony_ci pea LSIGSEGV 9062306a36Sopenharmony_ci jsr fpemu_signal 9162306a36Sopenharmony_ci add.w #12,%sp 9262306a36Sopenharmony_ci jra ret_from_exception 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#if defined(CONFIG_M68060) 9562306a36Sopenharmony_ci | send a trace signal if we are debugged 9662306a36Sopenharmony_ci | it does not really belong here, but... 9762306a36Sopenharmony_cifp_sendtrace060: 9862306a36Sopenharmony_ci move.l (FPS_PC,%sp),-(%sp) 9962306a36Sopenharmony_ci pea LTRAP_TRACE 10062306a36Sopenharmony_ci pea LSIGTRAP 10162306a36Sopenharmony_ci jsr fpemu_signal 10262306a36Sopenharmony_ci add.w #12,%sp 10362306a36Sopenharmony_ci jra ret_from_exception 10462306a36Sopenharmony_ci#endif 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci .globl fp_get_data_reg, fp_put_data_reg 10762306a36Sopenharmony_ci .globl fp_get_addr_reg, fp_put_addr_reg 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci | Entry points to get/put a register. Some of them can be get/put 11062306a36Sopenharmony_ci | directly, others are on the stack, as we read/write the stack 11162306a36Sopenharmony_ci | directly here, these function may only be called from within 11262306a36Sopenharmony_ci | instruction decoding, otherwise the stack pointer is incorrect 11362306a36Sopenharmony_ci | and the stack gets corrupted. 11462306a36Sopenharmony_cifp_get_data_reg: 11562306a36Sopenharmony_ci jmp ([0f:w,%pc,%d0.w*4]) 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci .align 4 11862306a36Sopenharmony_ci0: 11962306a36Sopenharmony_ci .long fp_get_d0, fp_get_d1 12062306a36Sopenharmony_ci .long fp_get_d2, fp_get_d3 12162306a36Sopenharmony_ci .long fp_get_d4, fp_get_d5 12262306a36Sopenharmony_ci .long fp_get_d6, fp_get_d7 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cifp_get_d0: 12562306a36Sopenharmony_ci move.l (PT_OFF_D0+8,%sp),%d0 12662306a36Sopenharmony_ci printf PREGISTER,"{d0->%08x}",1,%d0 12762306a36Sopenharmony_ci rts 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cifp_get_d1: 13062306a36Sopenharmony_ci move.l (PT_OFF_D1+8,%sp),%d0 13162306a36Sopenharmony_ci printf PREGISTER,"{d1->%08x}",1,%d0 13262306a36Sopenharmony_ci rts 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cifp_get_d2: 13562306a36Sopenharmony_ci move.l (PT_OFF_D2+8,%sp),%d0 13662306a36Sopenharmony_ci printf PREGISTER,"{d2->%08x}",1,%d0 13762306a36Sopenharmony_ci rts 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cifp_get_d3: 14062306a36Sopenharmony_ci move.l %d3,%d0 14162306a36Sopenharmony_ci printf PREGISTER,"{d3->%08x}",1,%d0 14262306a36Sopenharmony_ci rts 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cifp_get_d4: 14562306a36Sopenharmony_ci move.l %d4,%d0 14662306a36Sopenharmony_ci printf PREGISTER,"{d4->%08x}",1,%d0 14762306a36Sopenharmony_ci rts 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cifp_get_d5: 15062306a36Sopenharmony_ci move.l %d5,%d0 15162306a36Sopenharmony_ci printf PREGISTER,"{d5->%08x}",1,%d0 15262306a36Sopenharmony_ci rts 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cifp_get_d6: 15562306a36Sopenharmony_ci move.l %d6,%d0 15662306a36Sopenharmony_ci printf PREGISTER,"{d6->%08x}",1,%d0 15762306a36Sopenharmony_ci rts 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cifp_get_d7: 16062306a36Sopenharmony_ci move.l %d7,%d0 16162306a36Sopenharmony_ci printf PREGISTER,"{d7->%08x}",1,%d0 16262306a36Sopenharmony_ci rts 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cifp_put_data_reg: 16562306a36Sopenharmony_ci jmp ([0f:w,%pc,%d1.w*4]) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci .align 4 16862306a36Sopenharmony_ci0: 16962306a36Sopenharmony_ci .long fp_put_d0, fp_put_d1 17062306a36Sopenharmony_ci .long fp_put_d2, fp_put_d3 17162306a36Sopenharmony_ci .long fp_put_d4, fp_put_d5 17262306a36Sopenharmony_ci .long fp_put_d6, fp_put_d7 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cifp_put_d0: 17562306a36Sopenharmony_ci printf PREGISTER,"{d0<-%08x}",1,%d0 17662306a36Sopenharmony_ci move.l %d0,(PT_OFF_D0+8,%sp) 17762306a36Sopenharmony_ci rts 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cifp_put_d1: 18062306a36Sopenharmony_ci printf PREGISTER,"{d1<-%08x}",1,%d0 18162306a36Sopenharmony_ci move.l %d0,(PT_OFF_D1+8,%sp) 18262306a36Sopenharmony_ci rts 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cifp_put_d2: 18562306a36Sopenharmony_ci printf PREGISTER,"{d2<-%08x}",1,%d0 18662306a36Sopenharmony_ci move.l %d0,(PT_OFF_D2+8,%sp) 18762306a36Sopenharmony_ci rts 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cifp_put_d3: 19062306a36Sopenharmony_ci printf PREGISTER,"{d3<-%08x}",1,%d0 19162306a36Sopenharmony_ci| move.l %d0,%d3 19262306a36Sopenharmony_ci move.l %d0,(PT_OFF_D3+8,%sp) 19362306a36Sopenharmony_ci rts 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cifp_put_d4: 19662306a36Sopenharmony_ci printf PREGISTER,"{d4<-%08x}",1,%d0 19762306a36Sopenharmony_ci| move.l %d0,%d4 19862306a36Sopenharmony_ci move.l %d0,(PT_OFF_D4+8,%sp) 19962306a36Sopenharmony_ci rts 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cifp_put_d5: 20262306a36Sopenharmony_ci printf PREGISTER,"{d5<-%08x}",1,%d0 20362306a36Sopenharmony_ci| move.l %d0,%d5 20462306a36Sopenharmony_ci move.l %d0,(PT_OFF_D5+8,%sp) 20562306a36Sopenharmony_ci rts 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cifp_put_d6: 20862306a36Sopenharmony_ci printf PREGISTER,"{d6<-%08x}",1,%d0 20962306a36Sopenharmony_ci move.l %d0,%d6 21062306a36Sopenharmony_ci rts 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cifp_put_d7: 21362306a36Sopenharmony_ci printf PREGISTER,"{d7<-%08x}",1,%d0 21462306a36Sopenharmony_ci move.l %d0,%d7 21562306a36Sopenharmony_ci rts 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cifp_get_addr_reg: 21862306a36Sopenharmony_ci jmp ([0f:w,%pc,%d0.w*4]) 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci .align 4 22162306a36Sopenharmony_ci0: 22262306a36Sopenharmony_ci .long fp_get_a0, fp_get_a1 22362306a36Sopenharmony_ci .long fp_get_a2, fp_get_a3 22462306a36Sopenharmony_ci .long fp_get_a4, fp_get_a5 22562306a36Sopenharmony_ci .long fp_get_a6, fp_get_a7 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cifp_get_a0: 22862306a36Sopenharmony_ci move.l (PT_OFF_A0+8,%sp),%a0 22962306a36Sopenharmony_ci printf PREGISTER,"{a0->%08x}",1,%a0 23062306a36Sopenharmony_ci rts 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cifp_get_a1: 23362306a36Sopenharmony_ci move.l (PT_OFF_A1+8,%sp),%a0 23462306a36Sopenharmony_ci printf PREGISTER,"{a1->%08x}",1,%a0 23562306a36Sopenharmony_ci rts 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cifp_get_a2: 23862306a36Sopenharmony_ci move.l (PT_OFF_A2+8,%sp),%a0 23962306a36Sopenharmony_ci printf PREGISTER,"{a2->%08x}",1,%a0 24062306a36Sopenharmony_ci rts 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cifp_get_a3: 24362306a36Sopenharmony_ci move.l %a3,%a0 24462306a36Sopenharmony_ci printf PREGISTER,"{a3->%08x}",1,%a0 24562306a36Sopenharmony_ci rts 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cifp_get_a4: 24862306a36Sopenharmony_ci move.l %a4,%a0 24962306a36Sopenharmony_ci printf PREGISTER,"{a4->%08x}",1,%a0 25062306a36Sopenharmony_ci rts 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cifp_get_a5: 25362306a36Sopenharmony_ci move.l %a5,%a0 25462306a36Sopenharmony_ci printf PREGISTER,"{a5->%08x}",1,%a0 25562306a36Sopenharmony_ci rts 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cifp_get_a6: 25862306a36Sopenharmony_ci move.l %a6,%a0 25962306a36Sopenharmony_ci printf PREGISTER,"{a6->%08x}",1,%a0 26062306a36Sopenharmony_ci rts 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cifp_get_a7: 26362306a36Sopenharmony_ci move.l %usp,%a0 26462306a36Sopenharmony_ci printf PREGISTER,"{a7->%08x}",1,%a0 26562306a36Sopenharmony_ci rts 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cifp_put_addr_reg: 26862306a36Sopenharmony_ci jmp ([0f:w,%pc,%d0.w*4]) 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci .align 4 27162306a36Sopenharmony_ci0: 27262306a36Sopenharmony_ci .long fp_put_a0, fp_put_a1 27362306a36Sopenharmony_ci .long fp_put_a2, fp_put_a3 27462306a36Sopenharmony_ci .long fp_put_a4, fp_put_a5 27562306a36Sopenharmony_ci .long fp_put_a6, fp_put_a7 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cifp_put_a0: 27862306a36Sopenharmony_ci printf PREGISTER,"{a0<-%08x}",1,%a0 27962306a36Sopenharmony_ci move.l %a0,(PT_OFF_A0+8,%sp) 28062306a36Sopenharmony_ci rts 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cifp_put_a1: 28362306a36Sopenharmony_ci printf PREGISTER,"{a1<-%08x}",1,%a0 28462306a36Sopenharmony_ci move.l %a0,(PT_OFF_A1+8,%sp) 28562306a36Sopenharmony_ci rts 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cifp_put_a2: 28862306a36Sopenharmony_ci printf PREGISTER,"{a2<-%08x}",1,%a0 28962306a36Sopenharmony_ci move.l %a0,(PT_OFF_A2+8,%sp) 29062306a36Sopenharmony_ci rts 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cifp_put_a3: 29362306a36Sopenharmony_ci printf PREGISTER,"{a3<-%08x}",1,%a0 29462306a36Sopenharmony_ci move.l %a0,%a3 29562306a36Sopenharmony_ci rts 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cifp_put_a4: 29862306a36Sopenharmony_ci printf PREGISTER,"{a4<-%08x}",1,%a0 29962306a36Sopenharmony_ci move.l %a0,%a4 30062306a36Sopenharmony_ci rts 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cifp_put_a5: 30362306a36Sopenharmony_ci printf PREGISTER,"{a5<-%08x}",1,%a0 30462306a36Sopenharmony_ci move.l %a0,%a5 30562306a36Sopenharmony_ci rts 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cifp_put_a6: 30862306a36Sopenharmony_ci printf PREGISTER,"{a6<-%08x}",1,%a0 30962306a36Sopenharmony_ci move.l %a0,%a6 31062306a36Sopenharmony_ci rts 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cifp_put_a7: 31362306a36Sopenharmony_ci printf PREGISTER,"{a7<-%08x}",1,%a0 31462306a36Sopenharmony_ci move.l %a0,%usp 31562306a36Sopenharmony_ci rts 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci .data 31862306a36Sopenharmony_ci .align 4 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cifp_debugprint: 32162306a36Sopenharmony_ci| .long PMDECODE 32262306a36Sopenharmony_ci .long PMINSTR+PMDECODE+PMCONV+PMNORM 32362306a36Sopenharmony_ci| .long PMCONV+PMNORM+PMINSTR 32462306a36Sopenharmony_ci| .long 0 325