1/* 2 * fp_scan.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 "fp_emu.h" 39#include "fp_decode.h" 40 41 .globl fp_scan, fp_datasize 42 43 .data 44 45| %d2 - first two instr words 46| %d1 - operand size 47 48/* operand formats are: 49 50 Long = 0, i.e. fmove.l 51 Single, i.e. fmove.s 52 Extended, i.e. fmove.x 53 Packed-BCD, i.e. fmove.p 54 Word, i.e. fmove.w 55 Double, i.e. fmove.d 56*/ 57 58 .text 59 60| On entry: 61| FPDATA - base of emulated FPU registers 62 63fp_scan: 64| normal fpu instruction? (this excludes fsave/frestore) 65 fp_get_pc %a0 66 printf PDECODE,"%08x: ",1,%a0 67 getuser.b (%a0),%d0,fp_err_ua1,%a0 68 cmp.b #0xf2,%d0 | cpid = 1 69 jne fp_nonstd 70| first two instruction words are kept in %d2 71 getuser.l (%a0)+,%d2,fp_err_ua1,%a0 72 fp_put_pc %a0 73fp_decode_cond: | separate conditional instr 74 fp_decode_cond_instr_type 75 76 .long fp_decode_move, fp_fscc 77 .long fp_fbccw, fp_fbccl 78 79fp_decode_move: | separate move instr 80 fp_decode_move_instr_type 81 82 .long fp_fgen_fp, fp_ill 83 .long fp_fgen_ea, fp_fmove_fp2mem 84 .long fp_fmovem_cr, fp_fmovem_cr 85 .long fp_fmovem_fp, fp_fmovem_fp 86 87| now all arithmetic instr and a few move instr are left 88fp_fgen_fp: | source is a fpu register 89 clr.b (FPD_FPSR+2,FPDATA) | clear the exception byte 90 fp_decode_sourcespec 91 printf PDECODE,"f<op>.x fp%d",1,%d0 92 fp_get_fp_reg 93 lea (FPD_TEMPFP1,FPDATA),%a1 | copy src into a temp location 94 move.l (%a0)+,(%a1)+ 95 move.l (%a0)+,(%a1)+ 96 move.l (%a0),(%a1) 97 lea (-8,%a1),%a0 98 jra fp_getdest 99 100fp_fgen_ea: | source is <ea> 101 clr.b (FPD_FPSR+2,FPDATA) | clear the exception byte 102 | sort out fmovecr, keep data size in %d1 103 fp_decode_sourcespec 104 cmp.w #7,%d0 105 jeq fp_fmovecr 106 move.w %d0,%d1 | store data size twice in %d1 107 swap %d1 | one can be trashed below 108 move.w %d0,%d1 109#ifdef FPU_EMU_DEBUG 110 lea 0f,%a0 111 clr.l %d0 112 move.b (%a0,%d1.w),%d0 113 printf PDECODE,"f<op>.%c ",1,%d0 114 115 .data 1160: .byte 'l','s','x','p','w','d','b',0 117 .previous 118#endif 119 120/* 121 fp_getsource, fp_getdest 122 123 basically, we end up with a pointer to the source operand in 124 %a1, and a pointer to the destination operand in %a0. both 125 are, of course, 96-bit extended floating point numbers. 126*/ 127 128fp_getsource: 129 | decode addressing mode for source 130 fp_decode_addr_mode 131 132 .long fp_data, fp_ill 133 .long fp_indirect, fp_postinc 134 .long fp_predecr, fp_disp16 135 .long fp_extmode0, fp_extmode1 136 137 | addressing mode: data register direct 138fp_data: 139 fp_mode_data_direct 140 jsr fp_get_data_reg 141 lea (FPD_TEMPFP1,FPDATA),%a0 142 jmp ([0f:w,%pc,%d1.w*4]) 143 144 .align 4 1450: 146 .long fp_data_long, fp_data_single 147 .long fp_ill, fp_ill 148 .long fp_data_word, fp_ill 149 .long fp_data_byte, fp_ill 150 151 | data types that fit in an integer data register 152fp_data_byte: 153 extb.l %d0 154 jra fp_data_long 155 156fp_data_word: 157 ext.l %d0 158 159fp_data_long: 160 jsr fp_conv_long2ext 161 jra fp_getdest 162 163fp_data_single: 164 jsr fp_conv_single2ext 165 jra fp_getdest 166 167 | addressing mode: address register indirect 168fp_indirect: 169 fp_mode_addr_indirect 170 jra fp_fetchsource 171 172 | addressing mode: address register indirect with postincrement 173fp_postinc: 174 fp_mode_addr_indirect_postinc 175 jra fp_fetchsource 176 177 | addressing mode: address register indirect with predecrement 178fp_predecr: 179 fp_mode_addr_indirect_predec 180 jra fp_fetchsource 181 182 | addressing mode: address register/programm counter indirect 183 | with 16bit displacement 184fp_disp16: 185 fp_mode_addr_indirect_disp16 186 jra fp_fetchsource 187 188 | all other indirect addressing modes will finally end up here 189fp_extmode0: 190 fp_mode_addr_indirect_extmode0 191 jra fp_fetchsource 192 193| all pc relative addressing modes and immediate/absolute modes end up here 194| the first ones are sent to fp_extmode0 or fp_disp16 195| and only the latter are handled here 196fp_extmode1: 197 fp_decode_addr_reg 198 jmp ([0f:w,%pc,%d0*4]) 199 200 .align 4 2010: 202 .long fp_abs_short, fp_abs_long 203 .long fp_disp16, fp_extmode0 204 .long fp_immediate, fp_ill 205 .long fp_ill, fp_ill 206 207 | addressing mode: absolute short 208fp_abs_short: 209 fp_mode_abs_short 210 jra fp_fetchsource 211 212 | addressing mode: absolute long 213fp_abs_long: 214 fp_mode_abs_long 215 jra fp_fetchsource 216 217 | addressing mode: immediate data 218fp_immediate: 219 printf PDECODE,"#" 220 fp_get_pc %a0 221 move.w (fp_datasize,%d1.w*2),%d0 222 addq.w #1,%d0 223 and.w #-2,%d0 224#ifdef FPU_EMU_DEBUG 225 movem.l %d0/%d1,-(%sp) 226 movel %a0,%a1 227 clr.l %d1 228 jra 2f 2291: getuser.b (%a1)+,%d1,fp_err_ua1,%a1 230 printf PDECODE,"%02x",1,%d1 2312: dbra %d0,1b 232 movem.l (%sp)+,%d0/%d1 233#endif 234 lea (%a0,%d0.w),%a1 235 fp_put_pc %a1 236| jra fp_fetchsource 237 238fp_fetchsource: 239 move.l %a0,%a1 240 swap %d1 241 lea (FPD_TEMPFP1,FPDATA),%a0 242 jmp ([0f:w,%pc,%d1.w*4]) 243 244 .align 4 2450: .long fp_long, fp_single 246 .long fp_ext, fp_pack 247 .long fp_word, fp_double 248 .long fp_byte, fp_ill 249 250fp_long: 251 getuser.l (%a1),%d0,fp_err_ua1,%a1 252 jsr fp_conv_long2ext 253 jra fp_getdest 254 255fp_single: 256 getuser.l (%a1),%d0,fp_err_ua1,%a1 257 jsr fp_conv_single2ext 258 jra fp_getdest 259 260fp_ext: 261 getuser.l (%a1)+,%d0,fp_err_ua1,%a1 262 lsr.l #8,%d0 263 lsr.l #7,%d0 264 lsr.w #1,%d0 265 move.l %d0,(%a0)+ 266 getuser.l (%a1)+,%d0,fp_err_ua1,%a1 267 move.l %d0,(%a0)+ 268 getuser.l (%a1),%d0,fp_err_ua1,%a1 269 move.l %d0,(%a0) 270 subq.l #8,%a0 271 jra fp_getdest 272 273fp_pack: 274 /* not supported yet */ 275 jra fp_ill 276 277fp_word: 278 getuser.w (%a1),%d0,fp_err_ua1,%a1 279 ext.l %d0 280 jsr fp_conv_long2ext 281 jra fp_getdest 282 283fp_double: 284 jsr fp_conv_double2ext 285 jra fp_getdest 286 287fp_byte: 288 getuser.b (%a1),%d0,fp_err_ua1,%a1 289 extb.l %d0 290 jsr fp_conv_long2ext 291| jra fp_getdest 292 293fp_getdest: 294 move.l %a0,%a1 295 bfextu %d2{#22,#3},%d0 296 printf PDECODE,",fp%d\n",1,%d0 297 fp_get_fp_reg 298 movem.l %a0/%a1,-(%sp) 299 pea fp_finalrounding 300 bfextu %d2{#25,#7},%d0 301 jmp ([0f:w,%pc,%d0*4]) 302 303 .align 4 3040: 305 .long fp_fmove_mem2fp, fp_fint, fp_fsinh, fp_fintrz 306 .long fp_fsqrt, fp_ill, fp_flognp1, fp_ill 307 .long fp_fetoxm1, fp_ftanh, fp_fatan, fp_ill 308 .long fp_fasin, fp_fatanh, fp_fsin, fp_ftan 309 .long fp_fetox, fp_ftwotox, fp_ftentox, fp_ill 310 .long fp_flogn, fp_flog10, fp_flog2, fp_ill 311 .long fp_fabs, fp_fcosh, fp_fneg, fp_ill 312 .long fp_facos, fp_fcos, fp_fgetexp, fp_fgetman 313 .long fp_fdiv, fp_fmod, fp_fadd, fp_fmul 314 .long fpa_fsgldiv, fp_frem, fp_fscale, fpa_fsglmul 315 .long fp_fsub, fp_ill, fp_ill, fp_ill 316 .long fp_ill, fp_ill, fp_ill, fp_ill 317 .long fp_fsincos0, fp_fsincos1, fp_fsincos2, fp_fsincos3 318 .long fp_fsincos4, fp_fsincos5, fp_fsincos6, fp_fsincos7 319 .long fp_fcmp, fp_ill, fp_ftst, fp_ill 320 .long fp_ill, fp_ill, fp_ill, fp_ill 321 .long fp_fsmove, fp_fssqrt, fp_ill, fp_ill 322 .long fp_fdmove, fp_fdsqrt, fp_ill, fp_ill 323 .long fp_ill, fp_ill, fp_ill, fp_ill 324 .long fp_ill, fp_ill, fp_ill, fp_ill 325 .long fp_ill, fp_ill, fp_ill, fp_ill 326 .long fp_ill, fp_ill, fp_ill, fp_ill 327 .long fp_fsabs, fp_ill, fp_fsneg, fp_ill 328 .long fp_fdabs, fp_ill, fp_fdneg, fp_ill 329 .long fp_fsdiv, fp_ill, fp_fsadd, fp_fsmul 330 .long fp_fddiv, fp_ill, fp_fdadd, fp_fdmul 331 .long fp_fssub, fp_ill, fp_ill, fp_ill 332 .long fp_fdsub, fp_ill, fp_ill, fp_ill 333 .long fp_ill, fp_ill, fp_ill, fp_ill 334 .long fp_ill, fp_ill, fp_ill, fp_ill 335 .long fp_ill, fp_ill, fp_ill, fp_ill 336 .long fp_ill, fp_ill, fp_ill, fp_ill 337 338 | Instructions follow 339 340 | Move an (emulated) ROM constant 341fp_fmovecr: 342 bfextu %d2{#27,#5},%d0 343 printf PINSTR,"fp_fmovecr #%d",1,%d0 344 move.l %d0,%d1 345 add.l %d0,%d0 346 add.l %d1,%d0 347 lea (fp_constants,%d0*4),%a0 348 move.l #0x801cc0ff,%d0 349 addq.l #1,%d1 350 lsl.l %d1,%d0 351 jcc 1f 352 fp_set_sr FPSR_EXC_INEX2 | INEX2 exception 3531: moveq #-128,%d0 | continue with fmove 354 and.l %d0,%d2 355 jra fp_getdest 356 357 .data 358 .align 4 359fp_constants: 360 .long 0x00004000,0xc90fdaa2,0x2168c235 | pi 361 .extend 0,0,0,0,0,0,0,0,0,0 362 .long 0x00003ffd,0x9a209a84,0xfbcff798 | log10(2) 363 .long 0x00004000,0xadf85458,0xa2bb4a9a | e 364 .long 0x00003fff,0xb8aa3b29,0x5c17f0bc | log2(e) 365 .long 0x00003ffd,0xde5bd8a9,0x37287195 | log10(e) 366 .long 0x00000000,0x00000000,0x00000000 | 0.0 367 .long 0x00003ffe,0xb17217f7,0xd1cf79ac | 1n(2) 368 .long 0x00004000,0x935d8ddd,0xaaa8ac17 | 1n(10) 369 | read this as "1.0 * 2^0" - note the high bit in the mantissa 370 .long 0x00003fff,0x80000000,0x00000000 | 10^0 371 .long 0x00004002,0xa0000000,0x00000000 | 10^1 372 .long 0x00004005,0xc8000000,0x00000000 | 10^2 373 .long 0x0000400c,0x9c400000,0x00000000 | 10^4 374 .long 0x00004019,0xbebc2000,0x00000000 | 10^8 375 .long 0x00004034,0x8e1bc9bf,0x04000000 | 10^16 376 .long 0x00004069,0x9dc5ada8,0x2b70b59e | 10^32 377 .long 0x000040d3,0xc2781f49,0xffcfa6d5 | 10^64 378 .long 0x000041a8,0x93ba47c9,0x80e98ce0 | 10^128 379 .long 0x00004351,0xaa7eebfb,0x9df9de8e | 10^256 380 .long 0x000046a3,0xe319a0ae,0xa60e91c7 | 10^512 381 .long 0x00004d48,0xc9767586,0x81750c17 | 10^1024 382 .long 0x00005a92,0x9e8b3b5d,0xc53d5de5 | 10^2048 383 .long 0x00007525,0xc4605202,0x8a20979b | 10^4096 384 .previous 385 386fp_fmove_mem2fp: 387 printf PINSTR,"fmove %p,%p\n",2,%a0,%a1 388 move.l (%a1)+,(%a0)+ 389 move.l (%a1)+,(%a0)+ 390 move.l (%a1),(%a0) 391 subq.l #8,%a0 392 rts 393 394fpa_fsglmul: 395 move.l #fp_finalrounding_single_fast,(%sp) 396 jra fp_fsglmul 397 398fpa_fsgldiv: 399 move.l #fp_finalrounding_single_fast,(%sp) 400 jra fp_fsgldiv 401 402.macro fp_dosingleprec instr 403 printf PINSTR,"single " 404 move.l #fp_finalrounding_single,(%sp) 405 jra \instr 406.endm 407 408.macro fp_dodoubleprec instr 409 printf PINSTR,"double " 410 move.l #fp_finalrounding_double,(%sp) 411 jra \instr 412.endm 413 414fp_fsmove: 415 fp_dosingleprec fp_fmove_mem2fp 416 417fp_fssqrt: 418 fp_dosingleprec fp_fsqrt 419 420fp_fdmove: 421 fp_dodoubleprec fp_fmove_mem2fp 422 423fp_fdsqrt: 424 fp_dodoubleprec fp_fsqrt 425 426fp_fsabs: 427 fp_dosingleprec fp_fabs 428 429fp_fsneg: 430 fp_dosingleprec fp_fneg 431 432fp_fdabs: 433 fp_dodoubleprec fp_fabs 434 435fp_fdneg: 436 fp_dodoubleprec fp_fneg 437 438fp_fsdiv: 439 fp_dosingleprec fp_fdiv 440 441fp_fsadd: 442 fp_dosingleprec fp_fadd 443 444fp_fsmul: 445 fp_dosingleprec fp_fmul 446 447fp_fddiv: 448 fp_dodoubleprec fp_fdiv 449 450fp_fdadd: 451 fp_dodoubleprec fp_fadd 452 453fp_fdmul: 454 fp_dodoubleprec fp_fmul 455 456fp_fssub: 457 fp_dosingleprec fp_fsub 458 459fp_fdsub: 460 fp_dodoubleprec fp_fsub 461 462fp_nonstd: 463 fp_get_pc %a0 464 getuser.l (%a0),%d0,fp_err_ua1,%a0 465 printf ,"nonstd ((%08x)=%08x)\n",2,%a0,%d0 466 moveq #-1,%d0 467 rts 468 469 .data 470 .align 4 471 472 | data sizes corresponding to the operand formats 473fp_datasize: 474 .word 4, 4, 12, 12, 2, 8, 1, 0 475