1/* 2 * fp_emu.S 3 * 4 * Copyright Roman Zippel, 1997. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, and the entire permission notice in its entirety, 11 * including the disclaimer of warranties. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote 16 * products derived from this software without specific prior 17 * written permission. 18 * 19 * ALTERNATIVELY, this product may be distributed under the terms of 20 * the GNU General Public License, in which case the provisions of the GPL are 21 * required INSTEAD OF the above restrictions. (This clause is 22 * necessary due to a potential bad interaction between the GPL and 23 * the restrictions contained in a BSD-style copyright.) 24 * 25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 35 * OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <linux/linkage.h> 39#include <asm/entry.h> 40 41#include "fp_emu.h" 42 43 .globl fpu_emu 44 .globl fp_debugprint 45 .globl fp_err_ua1,fp_err_ua2 46 47 .text 48fpu_emu: 49 SAVE_ALL_INT 50 GET_CURRENT(%d0) 51 52#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) 53 tst.l m68k_is040or060 54 jeq 1f 55#endif 56#if defined(CPU_M68040_OR_M68060) 57 move.l (FPS_PC2,%sp),(FPS_PC,%sp) 58#endif 591: 60 | emulate the instruction 61 jsr fp_scan 62 63#if defined(CONFIG_M68060) 64#if !defined(CPU_M68060_ONLY) 65 btst #3,m68k_cputype+3 66 jeq 1f 67#endif 68 btst #7,(FPS_SR,%sp) 69 jne fp_sendtrace060 70#endif 711: 72 | emulation successful? 73 tst.l %d0 74 jeq ret_from_exception 75 76 | send some signal to program here 77 78 jra ret_from_exception 79 80 | we jump here after an access error while trying to access 81 | user space, we correct stackpointer and send a SIGSEGV to 82 | the user process 83fp_err_ua2: 84 addq.l #4,%sp 85fp_err_ua1: 86 addq.l #4,%sp 87 move.l %a0,-(%sp) 88 pea LSEGV_MAPERR 89 pea LSIGSEGV 90 jsr fpemu_signal 91 add.w #12,%sp 92 jra ret_from_exception 93 94#if defined(CONFIG_M68060) 95 | send a trace signal if we are debugged 96 | it does not really belong here, but... 97fp_sendtrace060: 98 move.l (FPS_PC,%sp),-(%sp) 99 pea LTRAP_TRACE 100 pea LSIGTRAP 101 jsr fpemu_signal 102 add.w #12,%sp 103 jra ret_from_exception 104#endif 105 106 .globl fp_get_data_reg, fp_put_data_reg 107 .globl fp_get_addr_reg, fp_put_addr_reg 108 109 | Entry points to get/put a register. Some of them can be get/put 110 | directly, others are on the stack, as we read/write the stack 111 | directly here, these function may only be called from within 112 | instruction decoding, otherwise the stack pointer is incorrect 113 | and the stack gets corrupted. 114fp_get_data_reg: 115 jmp ([0f:w,%pc,%d0.w*4]) 116 117 .align 4 1180: 119 .long fp_get_d0, fp_get_d1 120 .long fp_get_d2, fp_get_d3 121 .long fp_get_d4, fp_get_d5 122 .long fp_get_d6, fp_get_d7 123 124fp_get_d0: 125 move.l (PT_OFF_D0+8,%sp),%d0 126 printf PREGISTER,"{d0->%08x}",1,%d0 127 rts 128 129fp_get_d1: 130 move.l (PT_OFF_D1+8,%sp),%d0 131 printf PREGISTER,"{d1->%08x}",1,%d0 132 rts 133 134fp_get_d2: 135 move.l (PT_OFF_D2+8,%sp),%d0 136 printf PREGISTER,"{d2->%08x}",1,%d0 137 rts 138 139fp_get_d3: 140 move.l %d3,%d0 141 printf PREGISTER,"{d3->%08x}",1,%d0 142 rts 143 144fp_get_d4: 145 move.l %d4,%d0 146 printf PREGISTER,"{d4->%08x}",1,%d0 147 rts 148 149fp_get_d5: 150 move.l %d5,%d0 151 printf PREGISTER,"{d5->%08x}",1,%d0 152 rts 153 154fp_get_d6: 155 move.l %d6,%d0 156 printf PREGISTER,"{d6->%08x}",1,%d0 157 rts 158 159fp_get_d7: 160 move.l %d7,%d0 161 printf PREGISTER,"{d7->%08x}",1,%d0 162 rts 163 164fp_put_data_reg: 165 jmp ([0f:w,%pc,%d1.w*4]) 166 167 .align 4 1680: 169 .long fp_put_d0, fp_put_d1 170 .long fp_put_d2, fp_put_d3 171 .long fp_put_d4, fp_put_d5 172 .long fp_put_d6, fp_put_d7 173 174fp_put_d0: 175 printf PREGISTER,"{d0<-%08x}",1,%d0 176 move.l %d0,(PT_OFF_D0+8,%sp) 177 rts 178 179fp_put_d1: 180 printf PREGISTER,"{d1<-%08x}",1,%d0 181 move.l %d0,(PT_OFF_D1+8,%sp) 182 rts 183 184fp_put_d2: 185 printf PREGISTER,"{d2<-%08x}",1,%d0 186 move.l %d0,(PT_OFF_D2+8,%sp) 187 rts 188 189fp_put_d3: 190 printf PREGISTER,"{d3<-%08x}",1,%d0 191| move.l %d0,%d3 192 move.l %d0,(PT_OFF_D3+8,%sp) 193 rts 194 195fp_put_d4: 196 printf PREGISTER,"{d4<-%08x}",1,%d0 197| move.l %d0,%d4 198 move.l %d0,(PT_OFF_D4+8,%sp) 199 rts 200 201fp_put_d5: 202 printf PREGISTER,"{d5<-%08x}",1,%d0 203| move.l %d0,%d5 204 move.l %d0,(PT_OFF_D5+8,%sp) 205 rts 206 207fp_put_d6: 208 printf PREGISTER,"{d6<-%08x}",1,%d0 209 move.l %d0,%d6 210 rts 211 212fp_put_d7: 213 printf PREGISTER,"{d7<-%08x}",1,%d0 214 move.l %d0,%d7 215 rts 216 217fp_get_addr_reg: 218 jmp ([0f:w,%pc,%d0.w*4]) 219 220 .align 4 2210: 222 .long fp_get_a0, fp_get_a1 223 .long fp_get_a2, fp_get_a3 224 .long fp_get_a4, fp_get_a5 225 .long fp_get_a6, fp_get_a7 226 227fp_get_a0: 228 move.l (PT_OFF_A0+8,%sp),%a0 229 printf PREGISTER,"{a0->%08x}",1,%a0 230 rts 231 232fp_get_a1: 233 move.l (PT_OFF_A1+8,%sp),%a0 234 printf PREGISTER,"{a1->%08x}",1,%a0 235 rts 236 237fp_get_a2: 238 move.l (PT_OFF_A2+8,%sp),%a0 239 printf PREGISTER,"{a2->%08x}",1,%a0 240 rts 241 242fp_get_a3: 243 move.l %a3,%a0 244 printf PREGISTER,"{a3->%08x}",1,%a0 245 rts 246 247fp_get_a4: 248 move.l %a4,%a0 249 printf PREGISTER,"{a4->%08x}",1,%a0 250 rts 251 252fp_get_a5: 253 move.l %a5,%a0 254 printf PREGISTER,"{a5->%08x}",1,%a0 255 rts 256 257fp_get_a6: 258 move.l %a6,%a0 259 printf PREGISTER,"{a6->%08x}",1,%a0 260 rts 261 262fp_get_a7: 263 move.l %usp,%a0 264 printf PREGISTER,"{a7->%08x}",1,%a0 265 rts 266 267fp_put_addr_reg: 268 jmp ([0f:w,%pc,%d0.w*4]) 269 270 .align 4 2710: 272 .long fp_put_a0, fp_put_a1 273 .long fp_put_a2, fp_put_a3 274 .long fp_put_a4, fp_put_a5 275 .long fp_put_a6, fp_put_a7 276 277fp_put_a0: 278 printf PREGISTER,"{a0<-%08x}",1,%a0 279 move.l %a0,(PT_OFF_A0+8,%sp) 280 rts 281 282fp_put_a1: 283 printf PREGISTER,"{a1<-%08x}",1,%a0 284 move.l %a0,(PT_OFF_A1+8,%sp) 285 rts 286 287fp_put_a2: 288 printf PREGISTER,"{a2<-%08x}",1,%a0 289 move.l %a0,(PT_OFF_A2+8,%sp) 290 rts 291 292fp_put_a3: 293 printf PREGISTER,"{a3<-%08x}",1,%a0 294 move.l %a0,%a3 295 rts 296 297fp_put_a4: 298 printf PREGISTER,"{a4<-%08x}",1,%a0 299 move.l %a0,%a4 300 rts 301 302fp_put_a5: 303 printf PREGISTER,"{a5<-%08x}",1,%a0 304 move.l %a0,%a5 305 rts 306 307fp_put_a6: 308 printf PREGISTER,"{a6<-%08x}",1,%a0 309 move.l %a0,%a6 310 rts 311 312fp_put_a7: 313 printf PREGISTER,"{a7<-%08x}",1,%a0 314 move.l %a0,%usp 315 rts 316 317 .data 318 .align 4 319 320fp_debugprint: 321| .long PMDECODE 322 .long PMINSTR+PMDECODE+PMCONV+PMNORM 323| .long PMCONV+PMNORM+PMINSTR 324| .long 0 325