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/config.h> 39#include <linux/linkage.h> 40#include <asm/entry.h> 41 42#include "fp_emu.h" 43 44 .globl SYMBOL_NAME(fpu_emu) 45 .globl fp_debugprint 46 .globl fp_err_ua1,fp_err_ua2 47 48 .text 49SYMBOL_NAME_LABEL(fpu_emu) 50 SAVE_ALL_INT 51 GET_CURRENT(%d0) 52 53#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) 54 tst.l SYMBOL_NAME(m68k_is040or060) 55 jeq 1f 56#endif 57#if defined(CPU_M68040_OR_M68060) 58 move.l (FPS_PC2,%sp),(FPS_PC,%sp) 59#endif 601: 61 | emulate the instruction 62 jsr fp_scan 63 64#if defined(CONFIG_M68060) 65#if !defined(CPU_M68060_ONLY) 66 btst #3,SYMBOL_NAME(m68k_cputype)+3 67 jeq 1f 68#endif 69 btst #7,(FPS_SR,%sp) 70 jne fp_sendtrace060 71#endif 721: 73 | emulation successful? 74 tst.l %d0 75 jeq SYMBOL_NAME(ret_from_exception) 76 77 | send some signal to program here 78 79 jra SYMBOL_NAME(ret_from_exception) 80 81 | we jump here after an access error while trying to access 82 | user space, we correct stackpointer and send a SIGSEGV to 83 | the user process 84fp_err_ua2: 85 addq.l #4,%sp 86fp_err_ua1: 87 addq.l #4,%sp 88 move.l %a0,-(%sp) 89 pea SEGV_MAPERR 90 pea SIGSEGV 91 jsr SYMBOL_NAME(fpemu_signal) 92 add.w #12,%sp 93 jra SYMBOL_NAME(ret_from_exception) 94 95#if defined(CONFIG_M68060) 96 | send a trace signal if we are debugged 97 | it does not really belong here, but... 98fp_sendtrace060: 99 move.l (FPS_PC,%sp),-(%sp) 100 pea TRAP_TRACE 101 pea SIGTRAP 102 jsr SYMBOL_NAME(fpemu_signal) 103 add.w #12,%sp 104 jra SYMBOL_NAME(ret_from_exception) 105#endif 106 107 .globl fp_get_data_reg, fp_put_data_reg 108 .globl fp_get_addr_reg, fp_put_addr_reg 109 110 | Entry points to get/put a register. Some of them can be get/put 111 | directly, others are on the stack, as we read/write the stack 112 | directly here, these function may only be called from within 113 | instruction decoding, otherwise the stack pointer is incorrect 114 | and the stack gets corrupted. 115fp_get_data_reg: 116 jmp ([0f:w,%pc,%d0.w*4]) 117 118 .align 4 1190: 120 .long fp_get_d0, fp_get_d1 121 .long fp_get_d2, fp_get_d3 122 .long fp_get_d4, fp_get_d5 123 .long fp_get_d6, fp_get_d7 124 125fp_get_d0: 126 move.l (PT_D0+8,%sp),%d0 127 printf PREGISTER,"{d0->%08x}",1,%d0 128 rts 129 130fp_get_d1: 131 move.l (PT_D1+8,%sp),%d0 132 printf PREGISTER,"{d1->%08x}",1,%d0 133 rts 134 135fp_get_d2: 136 move.l (PT_D2+8,%sp),%d0 137 printf PREGISTER,"{d2->%08x}",1,%d0 138 rts 139 140fp_get_d3: 141 move.l %d3,%d0 142 printf PREGISTER,"{d3->%08x}",1,%d0 143 rts 144 145fp_get_d4: 146 move.l %d4,%d0 147 printf PREGISTER,"{d4->%08x}",1,%d0 148 rts 149 150fp_get_d5: 151 move.l %d5,%d0 152 printf PREGISTER,"{d5->%08x}",1,%d0 153 rts 154 155fp_get_d6: 156 move.l %d6,%d0 157 printf PREGISTER,"{d6->%08x}",1,%d0 158 rts 159 160fp_get_d7: 161 move.l %d7,%d0 162 printf PREGISTER,"{d7->%08x}",1,%d0 163 rts 164 165fp_put_data_reg: 166 jmp ([0f:w,%pc,%d1.w*4]) 167 168 .align 4 1690: 170 .long fp_put_d0, fp_put_d1 171 .long fp_put_d2, fp_put_d3 172 .long fp_put_d4, fp_put_d5 173 .long fp_put_d6, fp_put_d7 174 175fp_put_d0: 176 printf PREGISTER,"{d0<-%08x}",1,%d0 177 move.l %d0,(PT_D0+8,%sp) 178 rts 179 180fp_put_d1: 181 printf PREGISTER,"{d1<-%08x}",1,%d0 182 move.l %d0,(PT_D1+8,%sp) 183 rts 184 185fp_put_d2: 186 printf PREGISTER,"{d2<-%08x}",1,%d0 187 move.l %d0,(PT_D2+8,%sp) 188 rts 189 190fp_put_d3: 191 printf PREGISTER,"{d3<-%08x}",1,%d0 192| move.l %d0,%d3 193 move.l %d0,(PT_D3+8,%sp) 194 rts 195 196fp_put_d4: 197 printf PREGISTER,"{d4<-%08x}",1,%d0 198| move.l %d0,%d4 199 move.l %d0,(PT_D4+8,%sp) 200 rts 201 202fp_put_d5: 203 printf PREGISTER,"{d5<-%08x}",1,%d0 204| move.l %d0,%d5 205 move.l %d0,(PT_D5+8,%sp) 206 rts 207 208fp_put_d6: 209 printf PREGISTER,"{d6<-%08x}",1,%d0 210 move.l %d0,%d6 211 rts 212 213fp_put_d7: 214 printf PREGISTER,"{d7<-%08x}",1,%d0 215 move.l %d0,%d7 216 rts 217 218fp_get_addr_reg: 219 jmp ([0f:w,%pc,%d0.w*4]) 220 221 .align 4 2220: 223 .long fp_get_a0, fp_get_a1 224 .long fp_get_a2, fp_get_a3 225 .long fp_get_a4, fp_get_a5 226 .long fp_get_a6, fp_get_a7 227 228fp_get_a0: 229 move.l (PT_A0+8,%sp),%a0 230 printf PREGISTER,"{a0->%08x}",1,%a0 231 rts 232 233fp_get_a1: 234 move.l (PT_A1+8,%sp),%a0 235 printf PREGISTER,"{a1->%08x}",1,%a0 236 rts 237 238fp_get_a2: 239 move.l (PT_A2+8,%sp),%a0 240 printf PREGISTER,"{a2->%08x}",1,%a0 241 rts 242 243fp_get_a3: 244 move.l %a3,%a0 245 printf PREGISTER,"{a3->%08x}",1,%a0 246 rts 247 248fp_get_a4: 249 move.l %a4,%a0 250 printf PREGISTER,"{a4->%08x}",1,%a0 251 rts 252 253fp_get_a5: 254 move.l %a5,%a0 255 printf PREGISTER,"{a5->%08x}",1,%a0 256 rts 257 258fp_get_a6: 259 move.l %a6,%a0 260 printf PREGISTER,"{a6->%08x}",1,%a0 261 rts 262 263fp_get_a7: 264 move.l %usp,%a0 265 printf PREGISTER,"{a7->%08x}",1,%a0 266 rts 267 268fp_put_addr_reg: 269 jmp ([0f:w,%pc,%d0.w*4]) 270 271 .align 4 2720: 273 .long fp_put_a0, fp_put_a1 274 .long fp_put_a2, fp_put_a3 275 .long fp_put_a4, fp_put_a5 276 .long fp_put_a6, fp_put_a7 277 278fp_put_a0: 279 printf PREGISTER,"{a0<-%08x}",1,%a0 280 move.l %a0,(PT_A0+8,%sp) 281 rts 282 283fp_put_a1: 284 printf PREGISTER,"{a1<-%08x}",1,%a0 285 move.l %a0,(PT_A1+8,%sp) 286 rts 287 288fp_put_a2: 289 printf PREGISTER,"{a2<-%08x}",1,%a0 290 move.l %a0,(PT_A2+8,%sp) 291 rts 292 293fp_put_a3: 294 printf PREGISTER,"{a3<-%08x}",1,%a0 295 move.l %a0,%a3 296 rts 297 298fp_put_a4: 299 printf PREGISTER,"{a4<-%08x}",1,%a0 300 move.l %a0,%a4 301 rts 302 303fp_put_a5: 304 printf PREGISTER,"{a5<-%08x}",1,%a0 305 move.l %a0,%a5 306 rts 307 308fp_put_a6: 309 printf PREGISTER,"{a6<-%08x}",1,%a0 310 move.l %a0,%a6 311 rts 312 313fp_put_a7: 314 printf PREGISTER,"{a7<-%08x}",1,%a0 315 move.l %a0,%usp 316 rts 317 318 .data 319 .align 4 320 321fp_debugprint: 322| .long PMDECODE 323 .long PMINSTR+PMDECODE+PMCONV+PMNORM 324| .long PMCONV+PMNORM+PMINSTR 325| .long 0 326