1 /* 2 * fp_scan.S 3 * 4 * Copyright Roman Zippel, 1997. All rights r 5 * 6 * Redistribution and use in source and binary 7 * modification, are permitted provided that t 8 * are met: 9 * 1. Redistributions of source code must reta 10 * notice, and the entire permission notice 11 * including the disclaimer of warranties. 12 * 2. Redistributions in binary form must repr 13 * notice, this list of conditions and the 14 * documentation and/or other materials pro 15 * 3. The name of the author may not be used t 16 * products derived from this software with 17 * written permission. 18 * 19 * ALTERNATIVELY, this product may be distribu 20 * the GNU General Public License, in which ca 21 * required INSTEAD OF the above restrictions. 22 * necessary due to a potential bad interactio 23 * the restrictions contained in a BSD-style c 24 * 25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 27 * OF MERCHANTABILITY AND FITNESS FOR A PARTIC 28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR B 29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, O 30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILI 33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIG 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS S 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 63 fp_scan: 64 | normal fpu instruction? (this excludes fsave 65 fp_get_pc %a0 66 printf PDECODE,"%08x: ",1,%a0 67 getuser.b (%a0),%d0,fp_err_ua1,%a0 68 #if 1 69 cmp.b #0xf2,%d0 | cpid 70 #else 71 cmp.b #0xfc,%d0 | cpid 72 #endif 73 jne fp_nonstd 74 | first two instruction words are kept in %d2 75 getuser.l (%a0)+,%d2,fp_err_ua1,%a0 76 fp_put_pc %a0 77 fp_decode_cond: | sepa 78 fp_decode_cond_instr_type 79 80 .long fp_decode_move, fp_fscc 81 .long fp_fbccw, fp_fbccl 82 83 fp_decode_move: | sepa 84 fp_decode_move_instr_type 85 86 .long fp_fgen_fp, fp_ill 87 .long fp_fgen_ea, fp_fmove_fp2mem 88 .long fp_fmovem_cr, fp_fmovem_cr 89 .long fp_fmovem_fp, fp_fmovem_fp 90 91 | now all arithmetic instr and a few move inst 92 fp_fgen_fp: | sour 93 clr.b (FPD_FPSR+2,FPDATA) | clea 94 fp_decode_sourcespec 95 printf PDECODE,"f<op>.x fp%d",1,%d0 96 fp_get_fp_reg 97 lea (FPD_TEMPFP1,FPDATA),%a1 | cop 98 move.l (%a0)+,(%a1)+ 99 move.l (%a0)+,(%a1)+ 100 move.l (%a0),(%a1) 101 lea (-8,%a1),%a0 102 jra fp_getdest 103 104 fp_fgen_ea: | sour 105 clr.b (FPD_FPSR+2,FPDATA) | clea 106 | sort out fmovecr, keep data size in 107 fp_decode_sourcespec 108 cmp.w #7,%d0 109 jeq fp_fmovecr 110 move.w %d0,%d1 | stor 111 swap %d1 | one 112 move.w %d0,%d1 113 #ifdef FPU_EMU_DEBUG 114 lea 0f,%a0 115 clr.l %d0 116 move.b (%a0,%d1.w),%d0 117 printf PDECODE,"f<op>.%c ",1,%d0 118 119 .data 120 0: .byte 'l','s','x','p','w','d','b',0 121 .previous 122 #endif 123 124 /* 125 fp_getsource, fp_getdest 126 127 basically, we end up with a pointer to 128 %a1, and a pointer to the destination 129 are, of course, 96-bit extended floati 130 */ 131 132 fp_getsource: 133 | decode addressing mode for source 134 fp_decode_addr_mode 135 136 .long fp_data, fp_ill 137 .long fp_indirect, fp_postinc 138 .long fp_predecr, fp_disp16 139 .long fp_extmode0, fp_extmode1 140 141 | addressing mode: data register direc 142 fp_data: 143 fp_mode_data_direct 144 jsr fp_get_data_reg 145 lea (FPD_TEMPFP1,FPDATA),%a0 146 jmp ([0f:w,%pc,%d1.w*4]) 147 148 .align 4 149 0: 150 .long fp_data_long, fp_data_single 151 .long fp_ill, fp_ill 152 .long fp_data_word, fp_ill 153 .long fp_data_byte, fp_ill 154 155 | data types that fit in an integer da 156 fp_data_byte: 157 extb.l %d0 158 jra fp_data_long 159 160 fp_data_word: 161 ext.l %d0 162 163 fp_data_long: 164 jsr fp_conv_long2ext 165 jra fp_getdest 166 167 fp_data_single: 168 jsr fp_conv_single2ext 169 jra fp_getdest 170 171 | addressing mode: address register in 172 fp_indirect: 173 fp_mode_addr_indirect 174 jra fp_fetchsource 175 176 | addressing mode: address register in 177 fp_postinc: 178 fp_mode_addr_indirect_postinc 179 jra fp_fetchsource 180 181 | addressing mode: address register in 182 fp_predecr: 183 fp_mode_addr_indirect_predec 184 jra fp_fetchsource 185 186 | addressing mode: address register/pr 187 | with 16bit displace 188 fp_disp16: 189 fp_mode_addr_indirect_disp16 190 jra fp_fetchsource 191 192 | all other indirect addressing modes 193 fp_extmode0: 194 fp_mode_addr_indirect_extmode0 195 jra fp_fetchsource 196 197 | all pc relative addressing modes and immedia 198 | the first ones are sent to fp_extmode0 or fp 199 | and only the latter are handled here 200 fp_extmode1: 201 fp_decode_addr_reg 202 jmp ([0f:w,%pc,%d0*4]) 203 204 .align 4 205 0: 206 .long fp_abs_short, fp_abs_long 207 .long fp_disp16, fp_extmode0 208 .long fp_immediate, fp_ill 209 .long fp_ill, fp_ill 210 211 | addressing mode: absolute short 212 fp_abs_short: 213 fp_mode_abs_short 214 jra fp_fetchsource 215 216 | addressing mode: absolute long 217 fp_abs_long: 218 fp_mode_abs_long 219 jra fp_fetchsource 220 221 | addressing mode: immediate data 222 fp_immediate: 223 printf PDECODE,"#" 224 fp_get_pc %a0 225 move.w (fp_datasize,%d1.w*2),%d0 226 addq.w #1,%d0 227 and.w #-2,%d0 228 #ifdef FPU_EMU_DEBUG 229 movem.l %d0/%d1,-(%sp) 230 movel %a0,%a1 231 clr.l %d1 232 jra 2f 233 1: getuser.b (%a1)+,%d1,fp_err_ua1,%a1 234 printf PDECODE,"%02x",1,%d1 235 2: dbra %d0,1b 236 movem.l (%sp)+,%d0/%d1 237 #endif 238 lea (%a0,%d0.w),%a1 239 fp_put_pc %a1 240 | jra fp_fetchsource 241 242 fp_fetchsource: 243 move.l %a0,%a1 244 swap %d1 245 lea (FPD_TEMPFP1,FPDATA),%a0 246 jmp ([0f:w,%pc,%d1.w*4]) 247 248 .align 4 249 0: .long fp_long, fp_single 250 .long fp_ext, fp_pack 251 .long fp_word, fp_double 252 .long fp_byte, fp_ill 253 254 fp_long: 255 getuser.l (%a1),%d0,fp_err_ua1,%a1 256 jsr fp_conv_long2ext 257 jra fp_getdest 258 259 fp_single: 260 getuser.l (%a1),%d0,fp_err_ua1,%a1 261 jsr fp_conv_single2ext 262 jra fp_getdest 263 264 fp_ext: 265 getuser.l (%a1)+,%d0,fp_err_ua1,%a1 266 lsr.l #8,%d0 267 lsr.l #7,%d0 268 lsr.w #1,%d0 269 move.l %d0,(%a0)+ 270 getuser.l (%a1)+,%d0,fp_err_ua1,%a1 271 move.l %d0,(%a0)+ 272 getuser.l (%a1),%d0,fp_err_ua1,%a1 273 move.l %d0,(%a0) 274 subq.l #8,%a0 275 jra fp_getdest 276 277 fp_pack: 278 /* not supported yet */ 279 jra fp_ill 280 281 fp_word: 282 getuser.w (%a1),%d0,fp_err_ua1,%a1 283 ext.l %d0 284 jsr fp_conv_long2ext 285 jra fp_getdest 286 287 fp_double: 288 jsr fp_conv_double2ext 289 jra fp_getdest 290 291 fp_byte: 292 getuser.b (%a1),%d0,fp_err_ua1,%a1 293 extb.l %d0 294 jsr fp_conv_long2ext 295 | jra fp_getdest 296 297 fp_getdest: 298 move.l %a0,%a1 299 bfextu %d2{#22,#3},%d0 300 printf PDECODE,",fp%d\n",1,%d0 301 fp_get_fp_reg 302 movem.l %a0/%a1,-(%sp) 303 pea fp_finalrounding 304 bfextu %d2{#25,#7},%d0 305 jmp ([0f:w,%pc,%d0*4]) 306 307 .align 4 308 0: 309 .long fp_fmove_mem2fp, fp_fint, fp_f 310 .long fp_fsqrt, fp_ill, fp_flognp1, 311 .long fp_fetoxm1, fp_ftanh, fp_fatan 312 .long fp_fasin, fp_fatanh, fp_fsin, 313 .long fp_fetox, fp_ftwotox, fp_ftent 314 .long fp_flogn, fp_flog10, fp_flog2, 315 .long fp_fabs, fp_fcosh, fp_fneg, fp 316 .long fp_facos, fp_fcos, fp_fgetexp, 317 .long fp_fdiv, fp_fmod, fp_fadd, fp_ 318 .long fpa_fsgldiv, fp_frem, fp_fscal 319 .long fp_fsub, fp_ill, fp_ill, fp_il 320 .long fp_ill, fp_ill, fp_ill, fp_ill 321 .long fp_fsincos0, fp_fsincos1, fp_f 322 .long fp_fsincos4, fp_fsincos5, fp_f 323 .long fp_fcmp, fp_ill, fp_ftst, fp_i 324 .long fp_ill, fp_ill, fp_ill, fp_ill 325 .long fp_fsmove, fp_fssqrt, fp_ill, 326 .long fp_fdmove, fp_fdsqrt, fp_ill, 327 .long fp_ill, fp_ill, fp_ill, fp_ill 328 .long fp_ill, fp_ill, fp_ill, fp_ill 329 .long fp_ill, fp_ill, fp_ill, fp_ill 330 .long fp_ill, fp_ill, fp_ill, fp_ill 331 .long fp_fsabs, fp_ill, fp_fsneg, fp 332 .long fp_fdabs, fp_ill, fp_fdneg, fp 333 .long fp_fsdiv, fp_ill, fp_fsadd, fp 334 .long fp_fddiv, fp_ill, fp_fdadd, fp 335 .long fp_fssub, fp_ill, fp_ill, fp_i 336 .long fp_fdsub, fp_ill, fp_ill, fp_i 337 .long fp_ill, fp_ill, fp_ill, fp_ill 338 .long fp_ill, fp_ill, fp_ill, fp_ill 339 .long fp_ill, fp_ill, fp_ill, fp_ill 340 .long fp_ill, fp_ill, fp_ill, fp_ill 341 342 | Instructions follow 343 344 | Move an (emulated) ROM constant 345 fp_fmovecr: 346 bfextu %d2{#27,#5},%d0 347 printf PINSTR,"fp_fmovecr #%d",1,%d0 348 move.l %d0,%d1 349 add.l %d0,%d0 350 add.l %d1,%d0 351 lea (fp_constants,%d0*4),%a0 352 move.l #0x801cc0ff,%d0 353 addq.l #1,%d1 354 lsl.l %d1,%d0 355 jcc 1f 356 fp_set_sr FPSR_EXC_INEX2 357 1: moveq #-128,%d0 358 and.l %d0,%d2 359 jra fp_getdest 360 361 .data 362 .align 4 363 fp_constants: 364 .long 0x00004000,0xc90fdaa2,0x2168c2 365 .extend 0,0,0,0,0,0,0,0,0,0 366 .long 0x00003ffd,0x9a209a84,0xfbcff7 367 .long 0x00004000,0xadf85458,0xa2bb4a 368 .long 0x00003fff,0xb8aa3b29,0x5c17f0 369 .long 0x00003ffd,0xde5bd8a9,0x372871 370 .long 0x00000000,0x00000000,0x000000 371 .long 0x00003ffe,0xb17217f7,0xd1cf79 372 .long 0x00004000,0x935d8ddd,0xaaa8ac 373 | read this as "1.0 * 2^0" - note the 374 .long 0x00003fff,0x80000000,0x000000 375 .long 0x00004002,0xa0000000,0x000000 376 .long 0x00004005,0xc8000000,0x000000 377 .long 0x0000400c,0x9c400000,0x000000 378 .long 0x00004019,0xbebc2000,0x000000 379 .long 0x00004034,0x8e1bc9bf,0x040000 380 .long 0x00004069,0x9dc5ada8,0x2b70b5 381 .long 0x000040d3,0xc2781f49,0xffcfa6 382 .long 0x000041a8,0x93ba47c9,0x80e98c 383 .long 0x00004351,0xaa7eebfb,0x9df9de 384 .long 0x000046a3,0xe319a0ae,0xa60e91 385 .long 0x00004d48,0xc9767586,0x81750c 386 .long 0x00005a92,0x9e8b3b5d,0xc53d5d 387 .long 0x00007525,0xc4605202,0x8a2097 388 .previous 389 390 fp_fmove_mem2fp: 391 printf PINSTR,"fmove %p,%p\n",2,%a0,% 392 move.l (%a1)+,(%a0)+ 393 move.l (%a1)+,(%a0)+ 394 move.l (%a1),(%a0) 395 subq.l #8,%a0 396 rts 397 398 fpa_fsglmul: 399 move.l #fp_finalrounding_single_fast, 400 jra fp_fsglmul 401 402 fpa_fsgldiv: 403 move.l #fp_finalrounding_single_fast, 404 jra fp_fsgldiv 405 406 .macro fp_dosingleprec instr 407 printf PINSTR,"single " 408 move.l #fp_finalrounding_single,(%sp) 409 jra \instr 410 .endm 411 412 .macro fp_dodoubleprec instr 413 printf PINSTR,"double " 414 move.l #fp_finalrounding_double,(%sp) 415 jra \instr 416 .endm 417 418 fp_fsmove: 419 fp_dosingleprec fp_fmove_mem2fp 420 421 fp_fssqrt: 422 fp_dosingleprec fp_fsqrt 423 424 fp_fdmove: 425 fp_dodoubleprec fp_fmove_mem2fp 426 427 fp_fdsqrt: 428 fp_dodoubleprec fp_fsqrt 429 430 fp_fsabs: 431 fp_dosingleprec fp_fabs 432 433 fp_fsneg: 434 fp_dosingleprec fp_fneg 435 436 fp_fdabs: 437 fp_dodoubleprec fp_fabs 438 439 fp_fdneg: 440 fp_dodoubleprec fp_fneg 441 442 fp_fsdiv: 443 fp_dosingleprec fp_fdiv 444 445 fp_fsadd: 446 fp_dosingleprec fp_fadd 447 448 fp_fsmul: 449 fp_dosingleprec fp_fmul 450 451 fp_fddiv: 452 fp_dodoubleprec fp_fdiv 453 454 fp_fdadd: 455 fp_dodoubleprec fp_fadd 456 457 fp_fdmul: 458 fp_dodoubleprec fp_fmul 459 460 fp_fssub: 461 fp_dosingleprec fp_fsub 462 463 fp_fdsub: 464 fp_dodoubleprec fp_fsub 465 466 fp_nonstd: 467 fp_get_pc %a0 468 getuser.l (%a0),%d0,fp_err_ua1,%a0 469 printf ,"nonstd ((%08x)=%08x)\n",2,%a 470 moveq #-1,%d0 471 rts 472 473 .data 474 .align 4 475 476 | data sizes corresponding to the oper 477 fp_datasize: 478 .word 4, 4, 12, 12, 2, 8, 1, 0
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.