18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * fp_emu.S 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright Roman Zippel, 1997. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 78c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 88c2ecf20Sopenharmony_ci * are met: 98c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 108c2ecf20Sopenharmony_ci * notice, and the entire permission notice in its entirety, 118c2ecf20Sopenharmony_ci * including the disclaimer of warranties. 128c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 138c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 148c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 158c2ecf20Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote 168c2ecf20Sopenharmony_ci * products derived from this software without specific prior 178c2ecf20Sopenharmony_ci * written permission. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of 208c2ecf20Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL are 218c2ecf20Sopenharmony_ci * required INSTEAD OF the above restrictions. (This clause is 228c2ecf20Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and 238c2ecf20Sopenharmony_ci * the restrictions contained in a BSD-style copyright.) 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 268c2ecf20Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 278c2ecf20Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 288c2ecf20Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 298c2ecf20Sopenharmony_ci * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 308c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 318c2ecf20Sopenharmony_ci * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 328c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 338c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 348c2ecf20Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 358c2ecf20Sopenharmony_ci * OF THE POSSIBILITY OF SUCH DAMAGE. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include <linux/linkage.h> 398c2ecf20Sopenharmony_ci#include <asm/entry.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#include "fp_emu.h" 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci .globl fpu_emu 448c2ecf20Sopenharmony_ci .globl fp_debugprint 458c2ecf20Sopenharmony_ci .globl fp_err_ua1,fp_err_ua2 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci .text 488c2ecf20Sopenharmony_cifpu_emu: 498c2ecf20Sopenharmony_ci SAVE_ALL_INT 508c2ecf20Sopenharmony_ci GET_CURRENT(%d0) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) 538c2ecf20Sopenharmony_ci tst.l m68k_is040or060 548c2ecf20Sopenharmony_ci jeq 1f 558c2ecf20Sopenharmony_ci#endif 568c2ecf20Sopenharmony_ci#if defined(CPU_M68040_OR_M68060) 578c2ecf20Sopenharmony_ci move.l (FPS_PC2,%sp),(FPS_PC,%sp) 588c2ecf20Sopenharmony_ci#endif 598c2ecf20Sopenharmony_ci1: 608c2ecf20Sopenharmony_ci | emulate the instruction 618c2ecf20Sopenharmony_ci jsr fp_scan 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#if defined(CONFIG_M68060) 648c2ecf20Sopenharmony_ci#if !defined(CPU_M68060_ONLY) 658c2ecf20Sopenharmony_ci btst #3,m68k_cputype+3 668c2ecf20Sopenharmony_ci jeq 1f 678c2ecf20Sopenharmony_ci#endif 688c2ecf20Sopenharmony_ci btst #7,(FPS_SR,%sp) 698c2ecf20Sopenharmony_ci jne fp_sendtrace060 708c2ecf20Sopenharmony_ci#endif 718c2ecf20Sopenharmony_ci1: 728c2ecf20Sopenharmony_ci | emulation successful? 738c2ecf20Sopenharmony_ci tst.l %d0 748c2ecf20Sopenharmony_ci jeq ret_from_exception 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci | send some signal to program here 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci jra ret_from_exception 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci | we jump here after an access error while trying to access 818c2ecf20Sopenharmony_ci | user space, we correct stackpointer and send a SIGSEGV to 828c2ecf20Sopenharmony_ci | the user process 838c2ecf20Sopenharmony_cifp_err_ua2: 848c2ecf20Sopenharmony_ci addq.l #4,%sp 858c2ecf20Sopenharmony_cifp_err_ua1: 868c2ecf20Sopenharmony_ci addq.l #4,%sp 878c2ecf20Sopenharmony_ci move.l %a0,-(%sp) 888c2ecf20Sopenharmony_ci pea LSEGV_MAPERR 898c2ecf20Sopenharmony_ci pea LSIGSEGV 908c2ecf20Sopenharmony_ci jsr fpemu_signal 918c2ecf20Sopenharmony_ci add.w #12,%sp 928c2ecf20Sopenharmony_ci jra ret_from_exception 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#if defined(CONFIG_M68060) 958c2ecf20Sopenharmony_ci | send a trace signal if we are debugged 968c2ecf20Sopenharmony_ci | it does not really belong here, but... 978c2ecf20Sopenharmony_cifp_sendtrace060: 988c2ecf20Sopenharmony_ci move.l (FPS_PC,%sp),-(%sp) 998c2ecf20Sopenharmony_ci pea LTRAP_TRACE 1008c2ecf20Sopenharmony_ci pea LSIGTRAP 1018c2ecf20Sopenharmony_ci jsr fpemu_signal 1028c2ecf20Sopenharmony_ci add.w #12,%sp 1038c2ecf20Sopenharmony_ci jra ret_from_exception 1048c2ecf20Sopenharmony_ci#endif 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci .globl fp_get_data_reg, fp_put_data_reg 1078c2ecf20Sopenharmony_ci .globl fp_get_addr_reg, fp_put_addr_reg 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci | Entry points to get/put a register. Some of them can be get/put 1108c2ecf20Sopenharmony_ci | directly, others are on the stack, as we read/write the stack 1118c2ecf20Sopenharmony_ci | directly here, these function may only be called from within 1128c2ecf20Sopenharmony_ci | instruction decoding, otherwise the stack pointer is incorrect 1138c2ecf20Sopenharmony_ci | and the stack gets corrupted. 1148c2ecf20Sopenharmony_cifp_get_data_reg: 1158c2ecf20Sopenharmony_ci jmp ([0f:w,%pc,%d0.w*4]) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci .align 4 1188c2ecf20Sopenharmony_ci0: 1198c2ecf20Sopenharmony_ci .long fp_get_d0, fp_get_d1 1208c2ecf20Sopenharmony_ci .long fp_get_d2, fp_get_d3 1218c2ecf20Sopenharmony_ci .long fp_get_d4, fp_get_d5 1228c2ecf20Sopenharmony_ci .long fp_get_d6, fp_get_d7 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cifp_get_d0: 1258c2ecf20Sopenharmony_ci move.l (PT_OFF_D0+8,%sp),%d0 1268c2ecf20Sopenharmony_ci printf PREGISTER,"{d0->%08x}",1,%d0 1278c2ecf20Sopenharmony_ci rts 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cifp_get_d1: 1308c2ecf20Sopenharmony_ci move.l (PT_OFF_D1+8,%sp),%d0 1318c2ecf20Sopenharmony_ci printf PREGISTER,"{d1->%08x}",1,%d0 1328c2ecf20Sopenharmony_ci rts 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cifp_get_d2: 1358c2ecf20Sopenharmony_ci move.l (PT_OFF_D2+8,%sp),%d0 1368c2ecf20Sopenharmony_ci printf PREGISTER,"{d2->%08x}",1,%d0 1378c2ecf20Sopenharmony_ci rts 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cifp_get_d3: 1408c2ecf20Sopenharmony_ci move.l %d3,%d0 1418c2ecf20Sopenharmony_ci printf PREGISTER,"{d3->%08x}",1,%d0 1428c2ecf20Sopenharmony_ci rts 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cifp_get_d4: 1458c2ecf20Sopenharmony_ci move.l %d4,%d0 1468c2ecf20Sopenharmony_ci printf PREGISTER,"{d4->%08x}",1,%d0 1478c2ecf20Sopenharmony_ci rts 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cifp_get_d5: 1508c2ecf20Sopenharmony_ci move.l %d5,%d0 1518c2ecf20Sopenharmony_ci printf PREGISTER,"{d5->%08x}",1,%d0 1528c2ecf20Sopenharmony_ci rts 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cifp_get_d6: 1558c2ecf20Sopenharmony_ci move.l %d6,%d0 1568c2ecf20Sopenharmony_ci printf PREGISTER,"{d6->%08x}",1,%d0 1578c2ecf20Sopenharmony_ci rts 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cifp_get_d7: 1608c2ecf20Sopenharmony_ci move.l %d7,%d0 1618c2ecf20Sopenharmony_ci printf PREGISTER,"{d7->%08x}",1,%d0 1628c2ecf20Sopenharmony_ci rts 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cifp_put_data_reg: 1658c2ecf20Sopenharmony_ci jmp ([0f:w,%pc,%d1.w*4]) 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci .align 4 1688c2ecf20Sopenharmony_ci0: 1698c2ecf20Sopenharmony_ci .long fp_put_d0, fp_put_d1 1708c2ecf20Sopenharmony_ci .long fp_put_d2, fp_put_d3 1718c2ecf20Sopenharmony_ci .long fp_put_d4, fp_put_d5 1728c2ecf20Sopenharmony_ci .long fp_put_d6, fp_put_d7 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cifp_put_d0: 1758c2ecf20Sopenharmony_ci printf PREGISTER,"{d0<-%08x}",1,%d0 1768c2ecf20Sopenharmony_ci move.l %d0,(PT_OFF_D0+8,%sp) 1778c2ecf20Sopenharmony_ci rts 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cifp_put_d1: 1808c2ecf20Sopenharmony_ci printf PREGISTER,"{d1<-%08x}",1,%d0 1818c2ecf20Sopenharmony_ci move.l %d0,(PT_OFF_D1+8,%sp) 1828c2ecf20Sopenharmony_ci rts 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cifp_put_d2: 1858c2ecf20Sopenharmony_ci printf PREGISTER,"{d2<-%08x}",1,%d0 1868c2ecf20Sopenharmony_ci move.l %d0,(PT_OFF_D2+8,%sp) 1878c2ecf20Sopenharmony_ci rts 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cifp_put_d3: 1908c2ecf20Sopenharmony_ci printf PREGISTER,"{d3<-%08x}",1,%d0 1918c2ecf20Sopenharmony_ci| move.l %d0,%d3 1928c2ecf20Sopenharmony_ci move.l %d0,(PT_OFF_D3+8,%sp) 1938c2ecf20Sopenharmony_ci rts 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cifp_put_d4: 1968c2ecf20Sopenharmony_ci printf PREGISTER,"{d4<-%08x}",1,%d0 1978c2ecf20Sopenharmony_ci| move.l %d0,%d4 1988c2ecf20Sopenharmony_ci move.l %d0,(PT_OFF_D4+8,%sp) 1998c2ecf20Sopenharmony_ci rts 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cifp_put_d5: 2028c2ecf20Sopenharmony_ci printf PREGISTER,"{d5<-%08x}",1,%d0 2038c2ecf20Sopenharmony_ci| move.l %d0,%d5 2048c2ecf20Sopenharmony_ci move.l %d0,(PT_OFF_D5+8,%sp) 2058c2ecf20Sopenharmony_ci rts 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cifp_put_d6: 2088c2ecf20Sopenharmony_ci printf PREGISTER,"{d6<-%08x}",1,%d0 2098c2ecf20Sopenharmony_ci move.l %d0,%d6 2108c2ecf20Sopenharmony_ci rts 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cifp_put_d7: 2138c2ecf20Sopenharmony_ci printf PREGISTER,"{d7<-%08x}",1,%d0 2148c2ecf20Sopenharmony_ci move.l %d0,%d7 2158c2ecf20Sopenharmony_ci rts 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cifp_get_addr_reg: 2188c2ecf20Sopenharmony_ci jmp ([0f:w,%pc,%d0.w*4]) 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci .align 4 2218c2ecf20Sopenharmony_ci0: 2228c2ecf20Sopenharmony_ci .long fp_get_a0, fp_get_a1 2238c2ecf20Sopenharmony_ci .long fp_get_a2, fp_get_a3 2248c2ecf20Sopenharmony_ci .long fp_get_a4, fp_get_a5 2258c2ecf20Sopenharmony_ci .long fp_get_a6, fp_get_a7 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cifp_get_a0: 2288c2ecf20Sopenharmony_ci move.l (PT_OFF_A0+8,%sp),%a0 2298c2ecf20Sopenharmony_ci printf PREGISTER,"{a0->%08x}",1,%a0 2308c2ecf20Sopenharmony_ci rts 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cifp_get_a1: 2338c2ecf20Sopenharmony_ci move.l (PT_OFF_A1+8,%sp),%a0 2348c2ecf20Sopenharmony_ci printf PREGISTER,"{a1->%08x}",1,%a0 2358c2ecf20Sopenharmony_ci rts 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cifp_get_a2: 2388c2ecf20Sopenharmony_ci move.l (PT_OFF_A2+8,%sp),%a0 2398c2ecf20Sopenharmony_ci printf PREGISTER,"{a2->%08x}",1,%a0 2408c2ecf20Sopenharmony_ci rts 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cifp_get_a3: 2438c2ecf20Sopenharmony_ci move.l %a3,%a0 2448c2ecf20Sopenharmony_ci printf PREGISTER,"{a3->%08x}",1,%a0 2458c2ecf20Sopenharmony_ci rts 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cifp_get_a4: 2488c2ecf20Sopenharmony_ci move.l %a4,%a0 2498c2ecf20Sopenharmony_ci printf PREGISTER,"{a4->%08x}",1,%a0 2508c2ecf20Sopenharmony_ci rts 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cifp_get_a5: 2538c2ecf20Sopenharmony_ci move.l %a5,%a0 2548c2ecf20Sopenharmony_ci printf PREGISTER,"{a5->%08x}",1,%a0 2558c2ecf20Sopenharmony_ci rts 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cifp_get_a6: 2588c2ecf20Sopenharmony_ci move.l %a6,%a0 2598c2ecf20Sopenharmony_ci printf PREGISTER,"{a6->%08x}",1,%a0 2608c2ecf20Sopenharmony_ci rts 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cifp_get_a7: 2638c2ecf20Sopenharmony_ci move.l %usp,%a0 2648c2ecf20Sopenharmony_ci printf PREGISTER,"{a7->%08x}",1,%a0 2658c2ecf20Sopenharmony_ci rts 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cifp_put_addr_reg: 2688c2ecf20Sopenharmony_ci jmp ([0f:w,%pc,%d0.w*4]) 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci .align 4 2718c2ecf20Sopenharmony_ci0: 2728c2ecf20Sopenharmony_ci .long fp_put_a0, fp_put_a1 2738c2ecf20Sopenharmony_ci .long fp_put_a2, fp_put_a3 2748c2ecf20Sopenharmony_ci .long fp_put_a4, fp_put_a5 2758c2ecf20Sopenharmony_ci .long fp_put_a6, fp_put_a7 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cifp_put_a0: 2788c2ecf20Sopenharmony_ci printf PREGISTER,"{a0<-%08x}",1,%a0 2798c2ecf20Sopenharmony_ci move.l %a0,(PT_OFF_A0+8,%sp) 2808c2ecf20Sopenharmony_ci rts 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cifp_put_a1: 2838c2ecf20Sopenharmony_ci printf PREGISTER,"{a1<-%08x}",1,%a0 2848c2ecf20Sopenharmony_ci move.l %a0,(PT_OFF_A1+8,%sp) 2858c2ecf20Sopenharmony_ci rts 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cifp_put_a2: 2888c2ecf20Sopenharmony_ci printf PREGISTER,"{a2<-%08x}",1,%a0 2898c2ecf20Sopenharmony_ci move.l %a0,(PT_OFF_A2+8,%sp) 2908c2ecf20Sopenharmony_ci rts 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cifp_put_a3: 2938c2ecf20Sopenharmony_ci printf PREGISTER,"{a3<-%08x}",1,%a0 2948c2ecf20Sopenharmony_ci move.l %a0,%a3 2958c2ecf20Sopenharmony_ci rts 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cifp_put_a4: 2988c2ecf20Sopenharmony_ci printf PREGISTER,"{a4<-%08x}",1,%a0 2998c2ecf20Sopenharmony_ci move.l %a0,%a4 3008c2ecf20Sopenharmony_ci rts 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cifp_put_a5: 3038c2ecf20Sopenharmony_ci printf PREGISTER,"{a5<-%08x}",1,%a0 3048c2ecf20Sopenharmony_ci move.l %a0,%a5 3058c2ecf20Sopenharmony_ci rts 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cifp_put_a6: 3088c2ecf20Sopenharmony_ci printf PREGISTER,"{a6<-%08x}",1,%a0 3098c2ecf20Sopenharmony_ci move.l %a0,%a6 3108c2ecf20Sopenharmony_ci rts 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cifp_put_a7: 3138c2ecf20Sopenharmony_ci printf PREGISTER,"{a7<-%08x}",1,%a0 3148c2ecf20Sopenharmony_ci move.l %a0,%usp 3158c2ecf20Sopenharmony_ci rts 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci .data 3188c2ecf20Sopenharmony_ci .align 4 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cifp_debugprint: 3218c2ecf20Sopenharmony_ci| .long PMDECODE 3228c2ecf20Sopenharmony_ci .long PMINSTR+PMDECODE+PMCONV+PMNORM 3238c2ecf20Sopenharmony_ci| .long PMCONV+PMNORM+PMINSTR 3248c2ecf20Sopenharmony_ci| .long 0 325