1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 3M68000 Hi-Performance Microprocessor Division 4M68060 Software Package 5Production Release P1.00 -- October 10, 1994 6 7M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. 8 9THE SOFTWARE is provided on an "AS IS" basis and without warranty. 10To the maximum extent permitted by applicable law, 11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 13and any warranty against infringement with regard to the SOFTWARE 14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. 15 16To the maximum extent permitted by applicable law, 17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) 20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. 21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE. 22 23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE 24so long as this entire notice is retained without alteration in any modified and/or 25redistributed versions, and that such modified versions are clearly identified as such. 26No licenses are granted by implication, estoppel or otherwise under any patents 27or trademarks of Motorola, Inc. 28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29# 30# freal.s: 31# This file is appended to the top of the 060FPSP package 32# and contains the entry points into the package. The user, in 33# effect, branches to one of the branch table entries located 34# after _060FPSP_TABLE. 35# Also, subroutine stubs exist in this file (_fpsp_done for 36# example) that are referenced by the FPSP package itself in order 37# to call a given routine. The stub routine actually performs the 38# callout. The FPSP code does a "bsr" to the stub routine. This 39# extra layer of hierarchy adds a slight performance penalty but 40# it makes the FPSP code easier to read and more mainatinable. 41# 42 43set _off_bsun, 0x00 44set _off_snan, 0x04 45set _off_operr, 0x08 46set _off_ovfl, 0x0c 47set _off_unfl, 0x10 48set _off_dz, 0x14 49set _off_inex, 0x18 50set _off_fline, 0x1c 51set _off_fpu_dis, 0x20 52set _off_trap, 0x24 53set _off_trace, 0x28 54set _off_access, 0x2c 55set _off_done, 0x30 56 57set _off_imr, 0x40 58set _off_dmr, 0x44 59set _off_dmw, 0x48 60set _off_irw, 0x4c 61set _off_irl, 0x50 62set _off_drb, 0x54 63set _off_drw, 0x58 64set _off_drl, 0x5c 65set _off_dwb, 0x60 66set _off_dww, 0x64 67set _off_dwl, 0x68 68 69_060FPSP_TABLE: 70 71############################################################### 72 73# Here's the table of ENTRY POINTS for those linking the package. 74 bra.l _fpsp_snan 75 short 0x0000 76 bra.l _fpsp_operr 77 short 0x0000 78 bra.l _fpsp_ovfl 79 short 0x0000 80 bra.l _fpsp_unfl 81 short 0x0000 82 bra.l _fpsp_dz 83 short 0x0000 84 bra.l _fpsp_inex 85 short 0x0000 86 bra.l _fpsp_fline 87 short 0x0000 88 bra.l _fpsp_unsupp 89 short 0x0000 90 bra.l _fpsp_effadd 91 short 0x0000 92 93 space 56 94 95############################################################### 96 global _fpsp_done 97_fpsp_done: 98 mov.l %d0,-(%sp) 99 mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0 100 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 101 mov.l 0x4(%sp),%d0 102 rtd &0x4 103 104 global _real_ovfl 105_real_ovfl: 106 mov.l %d0,-(%sp) 107 mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0 108 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 109 mov.l 0x4(%sp),%d0 110 rtd &0x4 111 112 global _real_unfl 113_real_unfl: 114 mov.l %d0,-(%sp) 115 mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0 116 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 117 mov.l 0x4(%sp),%d0 118 rtd &0x4 119 120 global _real_inex 121_real_inex: 122 mov.l %d0,-(%sp) 123 mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0 124 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 125 mov.l 0x4(%sp),%d0 126 rtd &0x4 127 128 global _real_bsun 129_real_bsun: 130 mov.l %d0,-(%sp) 131 mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0 132 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 133 mov.l 0x4(%sp),%d0 134 rtd &0x4 135 136 global _real_operr 137_real_operr: 138 mov.l %d0,-(%sp) 139 mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0 140 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 141 mov.l 0x4(%sp),%d0 142 rtd &0x4 143 144 global _real_snan 145_real_snan: 146 mov.l %d0,-(%sp) 147 mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0 148 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 149 mov.l 0x4(%sp),%d0 150 rtd &0x4 151 152 global _real_dz 153_real_dz: 154 mov.l %d0,-(%sp) 155 mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0 156 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 157 mov.l 0x4(%sp),%d0 158 rtd &0x4 159 160 global _real_fline 161_real_fline: 162 mov.l %d0,-(%sp) 163 mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0 164 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 165 mov.l 0x4(%sp),%d0 166 rtd &0x4 167 168 global _real_fpu_disabled 169_real_fpu_disabled: 170 mov.l %d0,-(%sp) 171 mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0 172 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 173 mov.l 0x4(%sp),%d0 174 rtd &0x4 175 176 global _real_trap 177_real_trap: 178 mov.l %d0,-(%sp) 179 mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0 180 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 181 mov.l 0x4(%sp),%d0 182 rtd &0x4 183 184 global _real_trace 185_real_trace: 186 mov.l %d0,-(%sp) 187 mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0 188 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 189 mov.l 0x4(%sp),%d0 190 rtd &0x4 191 192 global _real_access 193_real_access: 194 mov.l %d0,-(%sp) 195 mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0 196 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 197 mov.l 0x4(%sp),%d0 198 rtd &0x4 199 200####################################### 201 202 global _imem_read 203_imem_read: 204 mov.l %d0,-(%sp) 205 mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0 206 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 207 mov.l 0x4(%sp),%d0 208 rtd &0x4 209 210 global _dmem_read 211_dmem_read: 212 mov.l %d0,-(%sp) 213 mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0 214 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 215 mov.l 0x4(%sp),%d0 216 rtd &0x4 217 218 global _dmem_write 219_dmem_write: 220 mov.l %d0,-(%sp) 221 mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0 222 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 223 mov.l 0x4(%sp),%d0 224 rtd &0x4 225 226 global _imem_read_word 227_imem_read_word: 228 mov.l %d0,-(%sp) 229 mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0 230 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 231 mov.l 0x4(%sp),%d0 232 rtd &0x4 233 234 global _imem_read_long 235_imem_read_long: 236 mov.l %d0,-(%sp) 237 mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0 238 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 239 mov.l 0x4(%sp),%d0 240 rtd &0x4 241 242 global _dmem_read_byte 243_dmem_read_byte: 244 mov.l %d0,-(%sp) 245 mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0 246 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 247 mov.l 0x4(%sp),%d0 248 rtd &0x4 249 250 global _dmem_read_word 251_dmem_read_word: 252 mov.l %d0,-(%sp) 253 mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0 254 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 255 mov.l 0x4(%sp),%d0 256 rtd &0x4 257 258 global _dmem_read_long 259_dmem_read_long: 260 mov.l %d0,-(%sp) 261 mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0 262 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 263 mov.l 0x4(%sp),%d0 264 rtd &0x4 265 266 global _dmem_write_byte 267_dmem_write_byte: 268 mov.l %d0,-(%sp) 269 mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0 270 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 271 mov.l 0x4(%sp),%d0 272 rtd &0x4 273 274 global _dmem_write_word 275_dmem_write_word: 276 mov.l %d0,-(%sp) 277 mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0 278 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 279 mov.l 0x4(%sp),%d0 280 rtd &0x4 281 282 global _dmem_write_long 283_dmem_write_long: 284 mov.l %d0,-(%sp) 285 mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0 286 pea.l (_060FPSP_TABLE-0x80,%pc,%d0) 287 mov.l 0x4(%sp),%d0 288 rtd &0x4 289 290# 291# This file contains a set of define statements for constants 292# in order to promote readability within the corecode itself. 293# 294 295set LOCAL_SIZE, 192 # stack frame size(bytes) 296set LV, -LOCAL_SIZE # stack offset 297 298set EXC_SR, 0x4 # stack status register 299set EXC_PC, 0x6 # stack pc 300set EXC_VOFF, 0xa # stacked vector offset 301set EXC_EA, 0xc # stacked <ea> 302 303set EXC_FP, 0x0 # frame pointer 304 305set EXC_AREGS, -68 # offset of all address regs 306set EXC_DREGS, -100 # offset of all data regs 307set EXC_FPREGS, -36 # offset of all fp regs 308 309set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7 310set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7 311set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6 312set EXC_A5, EXC_AREGS+(5*4) 313set EXC_A4, EXC_AREGS+(4*4) 314set EXC_A3, EXC_AREGS+(3*4) 315set EXC_A2, EXC_AREGS+(2*4) 316set EXC_A1, EXC_AREGS+(1*4) 317set EXC_A0, EXC_AREGS+(0*4) 318set EXC_D7, EXC_DREGS+(7*4) 319set EXC_D6, EXC_DREGS+(6*4) 320set EXC_D5, EXC_DREGS+(5*4) 321set EXC_D4, EXC_DREGS+(4*4) 322set EXC_D3, EXC_DREGS+(3*4) 323set EXC_D2, EXC_DREGS+(2*4) 324set EXC_D1, EXC_DREGS+(1*4) 325set EXC_D0, EXC_DREGS+(0*4) 326 327set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0 328set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1 329set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used) 330 331set FP_SCR1, LV+80 # fp scratch 1 332set FP_SCR1_EX, FP_SCR1+0 333set FP_SCR1_SGN, FP_SCR1+2 334set FP_SCR1_HI, FP_SCR1+4 335set FP_SCR1_LO, FP_SCR1+8 336 337set FP_SCR0, LV+68 # fp scratch 0 338set FP_SCR0_EX, FP_SCR0+0 339set FP_SCR0_SGN, FP_SCR0+2 340set FP_SCR0_HI, FP_SCR0+4 341set FP_SCR0_LO, FP_SCR0+8 342 343set FP_DST, LV+56 # fp destination operand 344set FP_DST_EX, FP_DST+0 345set FP_DST_SGN, FP_DST+2 346set FP_DST_HI, FP_DST+4 347set FP_DST_LO, FP_DST+8 348 349set FP_SRC, LV+44 # fp source operand 350set FP_SRC_EX, FP_SRC+0 351set FP_SRC_SGN, FP_SRC+2 352set FP_SRC_HI, FP_SRC+4 353set FP_SRC_LO, FP_SRC+8 354 355set USER_FPIAR, LV+40 # FP instr address register 356 357set USER_FPSR, LV+36 # FP status register 358set FPSR_CC, USER_FPSR+0 # FPSR condition codes 359set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte 360set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte 361set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte 362 363set USER_FPCR, LV+32 # FP control register 364set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable 365set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control 366 367set L_SCR3, LV+28 # integer scratch 3 368set L_SCR2, LV+24 # integer scratch 2 369set L_SCR1, LV+20 # integer scratch 1 370 371set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst) 372 373set EXC_TEMP2, LV+24 # temporary space 374set EXC_TEMP, LV+16 # temporary space 375 376set DTAG, LV+15 # destination operand type 377set STAG, LV+14 # source operand type 378 379set SPCOND_FLG, LV+10 # flag: special case (see below) 380 381set EXC_CC, LV+8 # saved condition codes 382set EXC_EXTWPTR, LV+4 # saved current PC (active) 383set EXC_EXTWORD, LV+2 # saved extension word 384set EXC_CMDREG, LV+2 # saved extension word 385set EXC_OPWORD, LV+0 # saved operation word 386 387################################ 388 389# Helpful macros 390 391set FTEMP, 0 # offsets within an 392set FTEMP_EX, 0 # extended precision 393set FTEMP_SGN, 2 # value saved in memory. 394set FTEMP_HI, 4 395set FTEMP_LO, 8 396set FTEMP_GRS, 12 397 398set LOCAL, 0 # offsets within an 399set LOCAL_EX, 0 # extended precision 400set LOCAL_SGN, 2 # value saved in memory. 401set LOCAL_HI, 4 402set LOCAL_LO, 8 403set LOCAL_GRS, 12 404 405set DST, 0 # offsets within an 406set DST_EX, 0 # extended precision 407set DST_HI, 4 # value saved in memory. 408set DST_LO, 8 409 410set SRC, 0 # offsets within an 411set SRC_EX, 0 # extended precision 412set SRC_HI, 4 # value saved in memory. 413set SRC_LO, 8 414 415set SGL_LO, 0x3f81 # min sgl prec exponent 416set SGL_HI, 0x407e # max sgl prec exponent 417set DBL_LO, 0x3c01 # min dbl prec exponent 418set DBL_HI, 0x43fe # max dbl prec exponent 419set EXT_LO, 0x0 # min ext prec exponent 420set EXT_HI, 0x7ffe # max ext prec exponent 421 422set EXT_BIAS, 0x3fff # extended precision bias 423set SGL_BIAS, 0x007f # single precision bias 424set DBL_BIAS, 0x03ff # double precision bias 425 426set NORM, 0x00 # operand type for STAG/DTAG 427set ZERO, 0x01 # operand type for STAG/DTAG 428set INF, 0x02 # operand type for STAG/DTAG 429set QNAN, 0x03 # operand type for STAG/DTAG 430set DENORM, 0x04 # operand type for STAG/DTAG 431set SNAN, 0x05 # operand type for STAG/DTAG 432set UNNORM, 0x06 # operand type for STAG/DTAG 433 434################## 435# FPSR/FPCR bits # 436################## 437set neg_bit, 0x3 # negative result 438set z_bit, 0x2 # zero result 439set inf_bit, 0x1 # infinite result 440set nan_bit, 0x0 # NAN result 441 442set q_sn_bit, 0x7 # sign bit of quotient byte 443 444set bsun_bit, 7 # branch on unordered 445set snan_bit, 6 # signalling NAN 446set operr_bit, 5 # operand error 447set ovfl_bit, 4 # overflow 448set unfl_bit, 3 # underflow 449set dz_bit, 2 # divide by zero 450set inex2_bit, 1 # inexact result 2 451set inex1_bit, 0 # inexact result 1 452 453set aiop_bit, 7 # accrued inexact operation bit 454set aovfl_bit, 6 # accrued overflow bit 455set aunfl_bit, 5 # accrued underflow bit 456set adz_bit, 4 # accrued dz bit 457set ainex_bit, 3 # accrued inexact bit 458 459############################# 460# FPSR individual bit masks # 461############################# 462set neg_mask, 0x08000000 # negative bit mask (lw) 463set inf_mask, 0x02000000 # infinity bit mask (lw) 464set z_mask, 0x04000000 # zero bit mask (lw) 465set nan_mask, 0x01000000 # nan bit mask (lw) 466 467set neg_bmask, 0x08 # negative bit mask (byte) 468set inf_bmask, 0x02 # infinity bit mask (byte) 469set z_bmask, 0x04 # zero bit mask (byte) 470set nan_bmask, 0x01 # nan bit mask (byte) 471 472set bsun_mask, 0x00008000 # bsun exception mask 473set snan_mask, 0x00004000 # snan exception mask 474set operr_mask, 0x00002000 # operr exception mask 475set ovfl_mask, 0x00001000 # overflow exception mask 476set unfl_mask, 0x00000800 # underflow exception mask 477set dz_mask, 0x00000400 # dz exception mask 478set inex2_mask, 0x00000200 # inex2 exception mask 479set inex1_mask, 0x00000100 # inex1 exception mask 480 481set aiop_mask, 0x00000080 # accrued illegal operation 482set aovfl_mask, 0x00000040 # accrued overflow 483set aunfl_mask, 0x00000020 # accrued underflow 484set adz_mask, 0x00000010 # accrued divide by zero 485set ainex_mask, 0x00000008 # accrued inexact 486 487###################################### 488# FPSR combinations used in the FPSP # 489###################################### 490set dzinf_mask, inf_mask+dz_mask+adz_mask 491set opnan_mask, nan_mask+operr_mask+aiop_mask 492set nzi_mask, 0x01ffffff #clears N, Z, and I 493set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask 494set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask 495set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask 496set inx1a_mask, inex1_mask+ainex_mask 497set inx2a_mask, inex2_mask+ainex_mask 498set snaniop_mask, nan_mask+snan_mask+aiop_mask 499set snaniop2_mask, snan_mask+aiop_mask 500set naniop_mask, nan_mask+aiop_mask 501set neginf_mask, neg_mask+inf_mask 502set infaiop_mask, inf_mask+aiop_mask 503set negz_mask, neg_mask+z_mask 504set opaop_mask, operr_mask+aiop_mask 505set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask 506set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask 507 508######### 509# misc. # 510######### 511set rnd_stky_bit, 29 # stky bit pos in longword 512 513set sign_bit, 0x7 # sign bit 514set signan_bit, 0x6 # signalling nan bit 515 516set sgl_thresh, 0x3f81 # minimum sgl exponent 517set dbl_thresh, 0x3c01 # minimum dbl exponent 518 519set x_mode, 0x0 # extended precision 520set s_mode, 0x4 # single precision 521set d_mode, 0x8 # double precision 522 523set rn_mode, 0x0 # round-to-nearest 524set rz_mode, 0x1 # round-to-zero 525set rm_mode, 0x2 # round-tp-minus-infinity 526set rp_mode, 0x3 # round-to-plus-infinity 527 528set mantissalen, 64 # length of mantissa in bits 529 530set BYTE, 1 # len(byte) == 1 byte 531set WORD, 2 # len(word) == 2 bytes 532set LONG, 4 # len(longword) == 2 bytes 533 534set BSUN_VEC, 0xc0 # bsun vector offset 535set INEX_VEC, 0xc4 # inexact vector offset 536set DZ_VEC, 0xc8 # dz vector offset 537set UNFL_VEC, 0xcc # unfl vector offset 538set OPERR_VEC, 0xd0 # operr vector offset 539set OVFL_VEC, 0xd4 # ovfl vector offset 540set SNAN_VEC, 0xd8 # snan vector offset 541 542########################### 543# SPecial CONDition FLaGs # 544########################### 545set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception 546set fbsun_flg, 0x02 # flag bit: bsun exception 547set mia7_flg, 0x04 # flag bit: (a7)+ <ea> 548set mda7_flg, 0x08 # flag bit: -(a7) <ea> 549set fmovm_flg, 0x40 # flag bit: fmovm instruction 550set immed_flg, 0x80 # flag bit: &<data> <ea> 551 552set ftrapcc_bit, 0x0 553set fbsun_bit, 0x1 554set mia7_bit, 0x2 555set mda7_bit, 0x3 556set immed_bit, 0x7 557 558################################## 559# TRANSCENDENTAL "LAST-OP" FLAGS # 560################################## 561set FMUL_OP, 0x0 # fmul instr performed last 562set FDIV_OP, 0x1 # fdiv performed last 563set FADD_OP, 0x2 # fadd performed last 564set FMOV_OP, 0x3 # fmov performed last 565 566############# 567# CONSTANTS # 568############# 569T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD 570T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL 571 572PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000 573PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000 574 575TWOBYPI: 576 long 0x3FE45F30,0x6DC9C883 577 578######################################################################### 579# XDEF **************************************************************** # 580# _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. # 581# # 582# This handler should be the first code executed upon taking the # 583# FP Overflow exception in an operating system. # 584# # 585# XREF **************************************************************** # 586# _imem_read_long() - read instruction longword # 587# fix_skewed_ops() - adjust src operand in fsave frame # 588# set_tag_x() - determine optype of src/dst operands # 589# store_fpreg() - store opclass 0 or 2 result to FP regfile # 590# unnorm_fix() - change UNNORM operands to NORM or ZERO # 591# load_fpn2() - load dst operand from FP regfile # 592# fout() - emulate an opclass 3 instruction # 593# tbl_unsupp - add of table of emulation routines for opclass 0,2 # 594# _fpsp_done() - "callout" for 060FPSP exit (all work done!) # 595# _real_ovfl() - "callout" for Overflow exception enabled code # 596# _real_inex() - "callout" for Inexact exception enabled code # 597# _real_trace() - "callout" for Trace exception code # 598# # 599# INPUT *************************************************************** # 600# - The system stack contains the FP Ovfl exception stack frame # 601# - The fsave frame contains the source operand # 602# # 603# OUTPUT ************************************************************** # 604# Overflow Exception enabled: # 605# - The system stack is unchanged # 606# - The fsave frame contains the adjusted src op for opclass 0,2 # 607# Overflow Exception disabled: # 608# - The system stack is unchanged # 609# - The "exception present" flag in the fsave frame is cleared # 610# # 611# ALGORITHM *********************************************************** # 612# On the 060, if an FP overflow is present as the result of any # 613# instruction, the 060 will take an overflow exception whether the # 614# exception is enabled or disabled in the FPCR. For the disabled case, # 615# This handler emulates the instruction to determine what the correct # 616# default result should be for the operation. This default result is # 617# then stored in either the FP regfile, data regfile, or memory. # 618# Finally, the handler exits through the "callout" _fpsp_done() # 619# denoting that no exceptional conditions exist within the machine. # 620# If the exception is enabled, then this handler must create the # 621# exceptional operand and plave it in the fsave state frame, and store # 622# the default result (only if the instruction is opclass 3). For # 623# exceptions enabled, this handler must exit through the "callout" # 624# _real_ovfl() so that the operating system enabled overflow handler # 625# can handle this case. # 626# Two other conditions exist. First, if overflow was disabled # 627# but the inexact exception was enabled, this handler must exit # 628# through the "callout" _real_inex() regardless of whether the result # 629# was inexact. # 630# Also, in the case of an opclass three instruction where # 631# overflow was disabled and the trace exception was enabled, this # 632# handler must exit through the "callout" _real_trace(). # 633# # 634######################################################################### 635 636 global _fpsp_ovfl 637_fpsp_ovfl: 638 639#$# sub.l &24,%sp # make room for src/dst 640 641 link.w %a6,&-LOCAL_SIZE # init stack frame 642 643 fsave FP_SRC(%a6) # grab the "busy" frame 644 645 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 646 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 647 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 648 649# the FPIAR holds the "current PC" of the faulting instruction 650 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 651 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 652 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 653 bsr.l _imem_read_long # fetch the instruction words 654 mov.l %d0,EXC_OPWORD(%a6) 655 656############################################################################## 657 658 btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out? 659 bne.w fovfl_out 660 661 662 lea FP_SRC(%a6),%a0 # pass: ptr to src op 663 bsr.l fix_skewed_ops # fix src op 664 665# since, I believe, only NORMs and DENORMs can come through here, 666# maybe we can avoid the subroutine call. 667 lea FP_SRC(%a6),%a0 # pass: ptr to src op 668 bsr.l set_tag_x # tag the operand type 669 mov.b %d0,STAG(%a6) # maybe NORM,DENORM 670 671# bit five of the fp extension word separates the monadic and dyadic operations 672# that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos 673# will never take this exception. 674 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic? 675 beq.b fovfl_extract # monadic 676 677 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg 678 bsr.l load_fpn2 # load dst into FP_DST 679 680 lea FP_DST(%a6),%a0 # pass: ptr to dst op 681 bsr.l set_tag_x # tag the operand type 682 cmpi.b %d0,&UNNORM # is operand an UNNORM? 683 bne.b fovfl_op2_done # no 684 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO 685fovfl_op2_done: 686 mov.b %d0,DTAG(%a6) # save dst optype tag 687 688fovfl_extract: 689 690#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6) 691#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6) 692#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6) 693#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6) 694#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6) 695#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6) 696 697 clr.l %d0 698 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode 699 700 mov.b 1+EXC_CMDREG(%a6),%d1 701 andi.w &0x007f,%d1 # extract extension 702 703 andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field 704 705 fmov.l &0x0,%fpcr # zero current control regs 706 fmov.l &0x0,%fpsr 707 708 lea FP_SRC(%a6),%a0 709 lea FP_DST(%a6),%a1 710 711# maybe we can make these entry points ONLY the OVFL entry points of each routine. 712 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr 713 jsr (tbl_unsupp.l,%pc,%d1.l*1) 714 715# the operation has been emulated. the result is in fp0. 716# the EXOP, if an exception occurred, is in fp1. 717# we must save the default result regardless of whether 718# traps are enabled or disabled. 719 bfextu EXC_CMDREG(%a6){&6:&3},%d0 720 bsr.l store_fpreg 721 722# the exceptional possibilities we have left ourselves with are ONLY overflow 723# and inexact. and, the inexact is such that overflow occurred and was disabled 724# but inexact was enabled. 725 btst &ovfl_bit,FPCR_ENABLE(%a6) 726 bne.b fovfl_ovfl_on 727 728 btst &inex2_bit,FPCR_ENABLE(%a6) 729 bne.b fovfl_inex_on 730 731 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 732 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 733 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 734 735 unlk %a6 736#$# add.l &24,%sp 737 bra.l _fpsp_done 738 739# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP 740# in fp1. now, simply jump to _real_ovfl()! 741fovfl_ovfl_on: 742 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack 743 744 mov.w &0xe005,2+FP_SRC(%a6) # save exc status 745 746 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 747 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 748 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 749 750 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s! 751 752 unlk %a6 753 754 bra.l _real_ovfl 755 756# overflow occurred but is disabled. meanwhile, inexact is enabled. Therefore, 757# we must jump to real_inex(). 758fovfl_inex_on: 759 760 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack 761 762 mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4 763 mov.w &0xe001,2+FP_SRC(%a6) # save exc status 764 765 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 766 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 767 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 768 769 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s! 770 771 unlk %a6 772 773 bra.l _real_inex 774 775######################################################################## 776fovfl_out: 777 778 779#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6) 780#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6) 781#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6) 782 783# the src operand is definitely a NORM(!), so tag it as such 784 mov.b &NORM,STAG(%a6) # set src optype tag 785 786 clr.l %d0 787 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode 788 789 and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field 790 791 fmov.l &0x0,%fpcr # zero current control regs 792 fmov.l &0x0,%fpsr 793 794 lea FP_SRC(%a6),%a0 # pass ptr to src operand 795 796 bsr.l fout 797 798 btst &ovfl_bit,FPCR_ENABLE(%a6) 799 bne.w fovfl_ovfl_on 800 801 btst &inex2_bit,FPCR_ENABLE(%a6) 802 bne.w fovfl_inex_on 803 804 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 805 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 806 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 807 808 unlk %a6 809#$# add.l &24,%sp 810 811 btst &0x7,(%sp) # is trace on? 812 beq.l _fpsp_done # no 813 814 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR 815 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024 816 bra.l _real_trace 817 818######################################################################### 819# XDEF **************************************************************** # 820# _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. # 821# # 822# This handler should be the first code executed upon taking the # 823# FP Underflow exception in an operating system. # 824# # 825# XREF **************************************************************** # 826# _imem_read_long() - read instruction longword # 827# fix_skewed_ops() - adjust src operand in fsave frame # 828# set_tag_x() - determine optype of src/dst operands # 829# store_fpreg() - store opclass 0 or 2 result to FP regfile # 830# unnorm_fix() - change UNNORM operands to NORM or ZERO # 831# load_fpn2() - load dst operand from FP regfile # 832# fout() - emulate an opclass 3 instruction # 833# tbl_unsupp - add of table of emulation routines for opclass 0,2 # 834# _fpsp_done() - "callout" for 060FPSP exit (all work done!) # 835# _real_ovfl() - "callout" for Overflow exception enabled code # 836# _real_inex() - "callout" for Inexact exception enabled code # 837# _real_trace() - "callout" for Trace exception code # 838# # 839# INPUT *************************************************************** # 840# - The system stack contains the FP Unfl exception stack frame # 841# - The fsave frame contains the source operand # 842# # 843# OUTPUT ************************************************************** # 844# Underflow Exception enabled: # 845# - The system stack is unchanged # 846# - The fsave frame contains the adjusted src op for opclass 0,2 # 847# Underflow Exception disabled: # 848# - The system stack is unchanged # 849# - The "exception present" flag in the fsave frame is cleared # 850# # 851# ALGORITHM *********************************************************** # 852# On the 060, if an FP underflow is present as the result of any # 853# instruction, the 060 will take an underflow exception whether the # 854# exception is enabled or disabled in the FPCR. For the disabled case, # 855# This handler emulates the instruction to determine what the correct # 856# default result should be for the operation. This default result is # 857# then stored in either the FP regfile, data regfile, or memory. # 858# Finally, the handler exits through the "callout" _fpsp_done() # 859# denoting that no exceptional conditions exist within the machine. # 860# If the exception is enabled, then this handler must create the # 861# exceptional operand and plave it in the fsave state frame, and store # 862# the default result (only if the instruction is opclass 3). For # 863# exceptions enabled, this handler must exit through the "callout" # 864# _real_unfl() so that the operating system enabled overflow handler # 865# can handle this case. # 866# Two other conditions exist. First, if underflow was disabled # 867# but the inexact exception was enabled and the result was inexact, # 868# this handler must exit through the "callout" _real_inex(). # 869# was inexact. # 870# Also, in the case of an opclass three instruction where # 871# underflow was disabled and the trace exception was enabled, this # 872# handler must exit through the "callout" _real_trace(). # 873# # 874######################################################################### 875 876 global _fpsp_unfl 877_fpsp_unfl: 878 879#$# sub.l &24,%sp # make room for src/dst 880 881 link.w %a6,&-LOCAL_SIZE # init stack frame 882 883 fsave FP_SRC(%a6) # grab the "busy" frame 884 885 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 886 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 887 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 888 889# the FPIAR holds the "current PC" of the faulting instruction 890 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 891 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 892 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 893 bsr.l _imem_read_long # fetch the instruction words 894 mov.l %d0,EXC_OPWORD(%a6) 895 896############################################################################## 897 898 btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out? 899 bne.w funfl_out 900 901 902 lea FP_SRC(%a6),%a0 # pass: ptr to src op 903 bsr.l fix_skewed_ops # fix src op 904 905 lea FP_SRC(%a6),%a0 # pass: ptr to src op 906 bsr.l set_tag_x # tag the operand type 907 mov.b %d0,STAG(%a6) # maybe NORM,DENORM 908 909# bit five of the fp ext word separates the monadic and dyadic operations 910# that can pass through fpsp_unfl(). remember that fcmp, and ftst 911# will never take this exception. 912 btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic? 913 beq.b funfl_extract # monadic 914 915# now, what's left that's not dyadic is fsincos. we can distinguish it 916# from all dyadics by the '0110xxx pattern 917 btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos? 918 bne.b funfl_extract # yes 919 920 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg 921 bsr.l load_fpn2 # load dst into FP_DST 922 923 lea FP_DST(%a6),%a0 # pass: ptr to dst op 924 bsr.l set_tag_x # tag the operand type 925 cmpi.b %d0,&UNNORM # is operand an UNNORM? 926 bne.b funfl_op2_done # no 927 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO 928funfl_op2_done: 929 mov.b %d0,DTAG(%a6) # save dst optype tag 930 931funfl_extract: 932 933#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6) 934#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6) 935#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6) 936#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6) 937#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6) 938#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6) 939 940 clr.l %d0 941 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode 942 943 mov.b 1+EXC_CMDREG(%a6),%d1 944 andi.w &0x007f,%d1 # extract extension 945 946 andi.l &0x00ff01ff,USER_FPSR(%a6) 947 948 fmov.l &0x0,%fpcr # zero current control regs 949 fmov.l &0x0,%fpsr 950 951 lea FP_SRC(%a6),%a0 952 lea FP_DST(%a6),%a1 953 954# maybe we can make these entry points ONLY the OVFL entry points of each routine. 955 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr 956 jsr (tbl_unsupp.l,%pc,%d1.l*1) 957 958 bfextu EXC_CMDREG(%a6){&6:&3},%d0 959 bsr.l store_fpreg 960 961# The `060 FPU multiplier hardware is such that if the result of a 962# multiply operation is the smallest possible normalized number 963# (0x00000000_80000000_00000000), then the machine will take an 964# underflow exception. Since this is incorrect, we need to check 965# if our emulation, after re-doing the operation, decided that 966# no underflow was called for. We do these checks only in 967# funfl_{unfl,inex}_on() because w/ both exceptions disabled, this 968# special case will simply exit gracefully with the correct result. 969 970# the exceptional possibilities we have left ourselves with are ONLY overflow 971# and inexact. and, the inexact is such that overflow occurred and was disabled 972# but inexact was enabled. 973 btst &unfl_bit,FPCR_ENABLE(%a6) 974 bne.b funfl_unfl_on 975 976funfl_chkinex: 977 btst &inex2_bit,FPCR_ENABLE(%a6) 978 bne.b funfl_inex_on 979 980funfl_exit: 981 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 982 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 983 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 984 985 unlk %a6 986#$# add.l &24,%sp 987 bra.l _fpsp_done 988 989# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP 990# in fp1 (don't forget to save fp0). what to do now? 991# well, we simply have to get to go to _real_unfl()! 992funfl_unfl_on: 993 994# The `060 FPU multiplier hardware is such that if the result of a 995# multiply operation is the smallest possible normalized number 996# (0x00000000_80000000_00000000), then the machine will take an 997# underflow exception. Since this is incorrect, we check here to see 998# if our emulation, after re-doing the operation, decided that 999# no underflow was called for. 1000 btst &unfl_bit,FPSR_EXCEPT(%a6)
1001 beq.w funfl_chkinex 1002 1003funfl_unfl_on2: 1004 fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack 1005 1006 mov.w &0xe003,2+FP_SRC(%a6) # save exc status 1007 1008 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 1009 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1010 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1011 1012 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s! 1013 1014 unlk %a6 1015 1016 bra.l _real_unfl 1017 1018# underflow occurred but is disabled. meanwhile, inexact is enabled. Therefore, 1019# we must jump to real_inex(). 1020funfl_inex_on: 1021 1022# The `060 FPU multiplier hardware is such that if the result of a 1023# multiply operation is the smallest possible normalized number 1024# (0x00000000_80000000_00000000), then the machine will take an 1025# underflow exception. 1026# But, whether bogus or not, if inexact is enabled AND it occurred, 1027# then we have to branch to real_inex. 1028 1029 btst &inex2_bit,FPSR_EXCEPT(%a6) 1030 beq.w funfl_exit 1031 1032funfl_inex_on2: 1033 1034 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack 1035 1036 mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4 1037 mov.w &0xe001,2+FP_SRC(%a6) # save exc status 1038 1039 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 1040 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1041 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1042 1043 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s! 1044 1045 unlk %a6 1046 1047 bra.l _real_inex 1048 1049####################################################################### 1050funfl_out: 1051 1052 1053#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6) 1054#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6) 1055#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6) 1056 1057# the src operand is definitely a NORM(!), so tag it as such 1058 mov.b &NORM,STAG(%a6) # set src optype tag 1059 1060 clr.l %d0 1061 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode 1062 1063 and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field 1064 1065 fmov.l &0x0,%fpcr # zero current control regs 1066 fmov.l &0x0,%fpsr 1067 1068 lea FP_SRC(%a6),%a0 # pass ptr to src operand 1069 1070 bsr.l fout 1071 1072 btst &unfl_bit,FPCR_ENABLE(%a6) 1073 bne.w funfl_unfl_on2 1074 1075 btst &inex2_bit,FPCR_ENABLE(%a6) 1076 bne.w funfl_inex_on2 1077 1078 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 1079 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1080 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1081 1082 unlk %a6 1083#$# add.l &24,%sp 1084 1085 btst &0x7,(%sp) # is trace on? 1086 beq.l _fpsp_done # no 1087 1088 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR 1089 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024 1090 bra.l _real_trace 1091 1092######################################################################### 1093# XDEF **************************************************************** # 1094# _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented # 1095# Data Type" exception. # 1096# # 1097# This handler should be the first code executed upon taking the # 1098# FP Unimplemented Data Type exception in an operating system. # 1099# # 1100# XREF **************************************************************** # 1101# _imem_read_{word,long}() - read instruction word/longword # 1102# fix_skewed_ops() - adjust src operand in fsave frame # 1103# set_tag_x() - determine optype of src/dst operands # 1104# store_fpreg() - store opclass 0 or 2 result to FP regfile # 1105# unnorm_fix() - change UNNORM operands to NORM or ZERO # 1106# load_fpn2() - load dst operand from FP regfile # 1107# load_fpn1() - load src operand from FP regfile # 1108# fout() - emulate an opclass 3 instruction # 1109# tbl_unsupp - add of table of emulation routines for opclass 0,2 # 1110# _real_inex() - "callout" to operating system inexact handler # 1111# _fpsp_done() - "callout" for exit; work all done # 1112# _real_trace() - "callout" for Trace enabled exception # 1113# funimp_skew() - adjust fsave src ops to "incorrect" value # 1114# _real_snan() - "callout" for SNAN exception # 1115# _real_operr() - "callout" for OPERR exception # 1116# _real_ovfl() - "callout" for OVFL exception # 1117# _real_unfl() - "callout" for UNFL exception # 1118# get_packed() - fetch packed operand from memory # 1119# # 1120# INPUT *************************************************************** # 1121# - The system stack contains the "Unimp Data Type" stk frame # 1122# - The fsave frame contains the ssrc op (for UNNORM/DENORM) # 1123# # 1124# OUTPUT ************************************************************** # 1125# If Inexact exception (opclass 3): # 1126# - The system stack is changed to an Inexact exception stk frame # 1127# If SNAN exception (opclass 3): # 1128# - The system stack is changed to an SNAN exception stk frame # 1129# If OPERR exception (opclass 3): # 1130# - The system stack is changed to an OPERR exception stk frame # 1131# If OVFL exception (opclass 3): # 1132# - The system stack is changed to an OVFL exception stk frame # 1133# If UNFL exception (opclass 3): # 1134# - The system stack is changed to an UNFL exception stack frame # 1135# If Trace exception enabled: # 1136# - The system stack is changed to a Trace exception stack frame # 1137# Else: (normal case) # 1138# - Correct result has been stored as appropriate # 1139# # 1140# ALGORITHM *********************************************************** # 1141# Two main instruction types can enter here: (1) DENORM or UNNORM # 1142# unimplemented data types. These can be either opclass 0,2 or 3 # 1143# instructions, and (2) PACKED unimplemented data format instructions # 1144# also of opclasses 0,2, or 3. # 1145# For UNNORM/DENORM opclass 0 and 2, the handler fetches the src # 1146# operand from the fsave state frame and the dst operand (if dyadic) # 1147# from the FP register file. The instruction is then emulated by # 1148# choosing an emulation routine from a table of routines indexed by # 1149# instruction type. Once the instruction has been emulated and result # 1150# saved, then we check to see if any enabled exceptions resulted from # 1151# instruction emulation. If none, then we exit through the "callout" # 1152# _fpsp_done(). If there is an enabled FP exception, then we insert # 1153# this exception into the FPU in the fsave state frame and then exit # 1154# through _fpsp_done(). # 1155# PACKED opclass 0 and 2 is similar in how the instruction is # 1156# emulated and exceptions handled. The differences occur in how the # 1157# handler loads the packed op (by calling get_packed() routine) and # 1158# by the fact that a Trace exception could be pending for PACKED ops. # 1159# If a Trace exception is pending, then the current exception stack # 1160# frame is changed to a Trace exception stack frame and an exit is # 1161# made through _real_trace(). # 1162# For UNNORM/DENORM opclass 3, the actual move out to memory is # 1163# performed by calling the routine fout(). If no exception should occur # 1164# as the result of emulation, then an exit either occurs through # 1165# _fpsp_done() or through _real_trace() if a Trace exception is pending # 1166# (a Trace stack frame must be created here, too). If an FP exception # 1167# should occur, then we must create an exception stack frame of that # 1168# type and jump to either _real_snan(), _real_operr(), _real_inex(), # 1169# _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 # 1170# emulation is performed in a similar manner. # 1171# # 1172######################################################################### 1173 1174# 1175# (1) DENORM and UNNORM (unimplemented) data types: 1176# 1177# post-instruction 1178# ***************** 1179# * EA * 1180# pre-instruction * * 1181# ***************** ***************** 1182# * 0x0 * 0x0dc * * 0x3 * 0x0dc * 1183# ***************** ***************** 1184# * Next * * Next * 1185# * PC * * PC * 1186# ***************** ***************** 1187# * SR * * SR * 1188# ***************** ***************** 1189# 1190# (2) PACKED format (unsupported) opclasses two and three: 1191# ***************** 1192# * EA * 1193# * * 1194# ***************** 1195# * 0x2 * 0x0dc * 1196# ***************** 1197# * Next * 1198# * PC * 1199# ***************** 1200# * SR * 1201# ***************** 1202# 1203 global _fpsp_unsupp 1204_fpsp_unsupp: 1205 1206 link.w %a6,&-LOCAL_SIZE # init stack frame 1207 1208 fsave FP_SRC(%a6) # save fp state 1209 1210 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 1211 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 1212 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 1213 1214 btst &0x5,EXC_SR(%a6) # user or supervisor mode? 1215 bne.b fu_s 1216fu_u: 1217 mov.l %usp,%a0 # fetch user stack pointer 1218 mov.l %a0,EXC_A7(%a6) # save on stack 1219 bra.b fu_cont 1220# if the exception is an opclass zero or two unimplemented data type 1221# exception, then the a7' calculated here is wrong since it doesn't 1222# stack an ea. however, we don't need an a7' for this case anyways. 1223fu_s: 1224 lea 0x4+EXC_EA(%a6),%a0 # load old a7' 1225 mov.l %a0,EXC_A7(%a6) # save on stack 1226 1227fu_cont: 1228 1229# the FPIAR holds the "current PC" of the faulting instruction 1230# the FPIAR should be set correctly for ALL exceptions passing through 1231# this point. 1232 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 1233 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 1234 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 1235 bsr.l _imem_read_long # fetch the instruction words 1236 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD 1237 1238############################ 1239 1240 clr.b SPCOND_FLG(%a6) # clear special condition flag 1241 1242# Separate opclass three (fpn-to-mem) ops since they have a different 1243# stack frame and protocol. 1244 btst &0x5,EXC_CMDREG(%a6) # is it an fmove out? 1245 bne.w fu_out # yes 1246 1247# Separate packed opclass two instructions. 1248 bfextu EXC_CMDREG(%a6){&0:&6},%d0 1249 cmpi.b %d0,&0x13 1250 beq.w fu_in_pack 1251 1252 1253# I'm not sure at this point what FPSR bits are valid for this instruction. 1254# so, since the emulation routines re-create them anyways, zero exception field 1255 andi.l &0x00ff00ff,USER_FPSR(%a6) # zero exception field 1256 1257 fmov.l &0x0,%fpcr # zero current control regs 1258 fmov.l &0x0,%fpsr 1259 1260# Opclass two w/ memory-to-fpn operation will have an incorrect extended 1261# precision format if the src format was single or double and the 1262# source data type was an INF, NAN, DENORM, or UNNORM 1263 lea FP_SRC(%a6),%a0 # pass ptr to input 1264 bsr.l fix_skewed_ops 1265 1266# we don't know whether the src operand or the dst operand (or both) is the 1267# UNNORM or DENORM. call the function that tags the operand type. if the 1268# input is an UNNORM, then convert it to a NORM, DENORM, or ZERO. 1269 lea FP_SRC(%a6),%a0 # pass: ptr to src op 1270 bsr.l set_tag_x # tag the operand type 1271 cmpi.b %d0,&UNNORM # is operand an UNNORM? 1272 bne.b fu_op2 # no 1273 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO 1274 1275fu_op2: 1276 mov.b %d0,STAG(%a6) # save src optype tag 1277 1278 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg 1279 1280# bit five of the fp extension word separates the monadic and dyadic operations 1281# at this point 1282 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic? 1283 beq.b fu_extract # monadic 1284 cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst? 1285 beq.b fu_extract # yes, so it's monadic, too 1286 1287 bsr.l load_fpn2 # load dst into FP_DST 1288 1289 lea FP_DST(%a6),%a0 # pass: ptr to dst op 1290 bsr.l set_tag_x # tag the operand type 1291 cmpi.b %d0,&UNNORM # is operand an UNNORM? 1292 bne.b fu_op2_done # no 1293 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO 1294fu_op2_done: 1295 mov.b %d0,DTAG(%a6) # save dst optype tag 1296 1297fu_extract: 1298 clr.l %d0 1299 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec 1300 1301 bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension 1302 1303 lea FP_SRC(%a6),%a0 1304 lea FP_DST(%a6),%a1 1305 1306 mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr 1307 jsr (tbl_unsupp.l,%pc,%d1.l*1) 1308 1309# 1310# Exceptions in order of precedence: 1311# BSUN : none 1312# SNAN : all dyadic ops 1313# OPERR : fsqrt(-NORM) 1314# OVFL : all except ftst,fcmp 1315# UNFL : all except ftst,fcmp 1316# DZ : fdiv 1317# INEX2 : all except ftst,fcmp 1318# INEX1 : none (packed doesn't go through here) 1319# 1320 1321# we determine the highest priority exception(if any) set by the 1322# emulation routine that has also been enabled by the user. 1323 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions set 1324 bne.b fu_in_ena # some are enabled 1325 1326fu_in_cont: 1327# fcmp and ftst do not store any result. 1328 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension 1329 andi.b &0x38,%d0 # extract bits 3-5 1330 cmpi.b %d0,&0x38 # is instr fcmp or ftst? 1331 beq.b fu_in_exit # yes 1332 1333 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg 1334 bsr.l store_fpreg # store the result 1335 1336fu_in_exit: 1337 1338 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1339 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1340 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1341 1342 unlk %a6 1343 1344 bra.l _fpsp_done 1345 1346fu_in_ena: 1347 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled 1348 bfffo %d0{&24:&8},%d0 # find highest priority exception 1349 bne.b fu_in_exc # there is at least one set 1350 1351# 1352# No exceptions occurred that were also enabled. Now: 1353# 1354# if (OVFL && ovfl_disabled && inexact_enabled) { 1355# branch to _real_inex() (even if the result was exact!); 1356# } else { 1357# save the result in the proper fp reg (unless the op is fcmp or ftst); 1358# return; 1359# } 1360# 1361 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set? 1362 beq.b fu_in_cont # no 1363 1364fu_in_ovflchk: 1365 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled? 1366 beq.b fu_in_cont # no 1367 bra.w fu_in_exc_ovfl # go insert overflow frame 1368 1369# 1370# An exception occurred and that exception was enabled: 1371# 1372# shift enabled exception field into lo byte of d0; 1373# if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) || 1374# ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) { 1375# /* 1376# * this is the case where we must call _real_inex() now or else 1377# * there will be no other way to pass it the exceptional operand 1378# */ 1379# call _real_inex(); 1380# } else { 1381# restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU; 1382# } 1383# 1384fu_in_exc: 1385 subi.l &24,%d0 # fix offset to be 0-8 1386 cmpi.b %d0,&0x6 # is exception INEX? (6) 1387 bne.b fu_in_exc_exit # no 1388 1389# the enabled exception was inexact 1390 btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur? 1391 bne.w fu_in_exc_unfl # yes 1392 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur? 1393 bne.w fu_in_exc_ovfl # yes 1394 1395# here, we insert the correct fsave status value into the fsave frame for the 1396# corresponding exception. the operand in the fsave frame should be the original 1397# src operand. 1398fu_in_exc_exit: 1399 mov.l %d0,-(%sp) # save d0 1400 bsr.l funimp_skew # skew sgl or dbl inputs 1401 mov.l (%sp)+,%d0 # restore d0 1402 1403 mov.w (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status 1404 1405 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1406 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1407 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1408 1409 frestore FP_SRC(%a6) # restore src op 1410 1411 unlk %a6 1412 1413 bra.l _fpsp_done 1414 1415tbl_except: 1416 short 0xe000,0xe006,0xe004,0xe005 1417 short 0xe003,0xe002,0xe001,0xe001 1418 1419fu_in_exc_unfl: 1420 mov.w &0x4,%d0 1421 bra.b fu_in_exc_exit 1422fu_in_exc_ovfl: 1423 mov.w &0x03,%d0 1424 bra.b fu_in_exc_exit 1425 1426# If the input operand to this operation was opclass two and a single 1427# or double precision denorm, inf, or nan, the operand needs to be 1428# "corrected" in order to have the proper equivalent extended precision 1429# number. 1430 global fix_skewed_ops 1431fix_skewed_ops: 1432 bfextu EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt 1433 cmpi.b %d0,&0x11 # is class = 2 & fmt = sgl? 1434 beq.b fso_sgl # yes 1435 cmpi.b %d0,&0x15 # is class = 2 & fmt = dbl? 1436 beq.b fso_dbl # yes 1437 rts # no 1438 1439fso_sgl: 1440 mov.w LOCAL_EX(%a0),%d0 # fetch src exponent 1441 andi.w &0x7fff,%d0 # strip sign 1442 cmpi.w %d0,&0x3f80 # is |exp| == $3f80? 1443 beq.b fso_sgl_dnrm_zero # yes 1444 cmpi.w %d0,&0x407f # no; is |exp| == $407f? 1445 beq.b fso_infnan # yes 1446 rts # no 1447 1448fso_sgl_dnrm_zero: 1449 andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit 1450 beq.b fso_zero # it's a skewed zero 1451fso_sgl_dnrm: 1452# here, we count on norm not to alter a0... 1453 bsr.l norm # normalize mantissa 1454 neg.w %d0 # -shft amt 1455 addi.w &0x3f81,%d0 # adjust new exponent 1456 andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent 1457 or.w %d0,LOCAL_EX(%a0) # insert new exponent 1458 rts 1459 1460fso_zero: 1461 andi.w &0x8000,LOCAL_EX(%a0) # clear bogus exponent 1462 rts 1463 1464fso_infnan: 1465 andi.b &0x7f,LOCAL_HI(%a0) # clear j-bit 1466 ori.w &0x7fff,LOCAL_EX(%a0) # make exponent = $7fff 1467 rts 1468 1469fso_dbl: 1470 mov.w LOCAL_EX(%a0),%d0 # fetch src exponent 1471 andi.w &0x7fff,%d0 # strip sign 1472 cmpi.w %d0,&0x3c00 # is |exp| == $3c00? 1473 beq.b fso_dbl_dnrm_zero # yes 1474 cmpi.w %d0,&0x43ff # no; is |exp| == $43ff? 1475 beq.b fso_infnan # yes 1476 rts # no 1477 1478fso_dbl_dnrm_zero: 1479 andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit 1480 bne.b fso_dbl_dnrm # it's a skewed denorm 1481 tst.l LOCAL_LO(%a0) # is it a zero? 1482 beq.b fso_zero # yes 1483fso_dbl_dnrm: 1484# here, we count on norm not to alter a0... 1485 bsr.l norm # normalize mantissa 1486 neg.w %d0 # -shft amt 1487 addi.w &0x3c01,%d0 # adjust new exponent 1488 andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent 1489 or.w %d0,LOCAL_EX(%a0) # insert new exponent 1490 rts 1491 1492################################################################# 1493 1494# fmove out took an unimplemented data type exception. 1495# the src operand is in FP_SRC. Call _fout() to write out the result and 1496# to determine which exceptions, if any, to take. 1497fu_out: 1498 1499# Separate packed move outs from the UNNORM and DENORM move outs. 1500 bfextu EXC_CMDREG(%a6){&3:&3},%d0 1501 cmpi.b %d0,&0x3 1502 beq.w fu_out_pack 1503 cmpi.b %d0,&0x7 1504 beq.w fu_out_pack 1505 1506 1507# I'm not sure at this point what FPSR bits are valid for this instruction. 1508# so, since the emulation routines re-create them anyways, zero exception field. 1509# fmove out doesn't affect ccodes. 1510 and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field 1511 1512 fmov.l &0x0,%fpcr # zero current control regs 1513 fmov.l &0x0,%fpsr 1514 1515# the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine 1516# call here. just figure out what it is... 1517 mov.w FP_SRC_EX(%a6),%d0 # get exponent 1518 andi.w &0x7fff,%d0 # strip sign 1519 beq.b fu_out_denorm # it's a DENORM 1520 1521 lea FP_SRC(%a6),%a0 1522 bsr.l unnorm_fix # yes; fix it 1523 1524 mov.b %d0,STAG(%a6) 1525 1526 bra.b fu_out_cont 1527fu_out_denorm: 1528 mov.b &DENORM,STAG(%a6) 1529fu_out_cont: 1530 1531 clr.l %d0 1532 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec 1533 1534 lea FP_SRC(%a6),%a0 # pass ptr to src operand 1535 1536 mov.l (%a6),EXC_A6(%a6) # in case a6 changes 1537 bsr.l fout # call fmove out routine 1538 1539# Exceptions in order of precedence: 1540# BSUN : none 1541# SNAN : none 1542# OPERR : fmove.{b,w,l} out of large UNNORM 1543# OVFL : fmove.{s,d} 1544# UNFL : fmove.{s,d,x} 1545# DZ : none 1546# INEX2 : all 1547# INEX1 : none (packed doesn't travel through here) 1548 1549# determine the highest priority exception(if any) set by the 1550# emulation routine that has also been enabled by the user. 1551 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled 1552 bne.w fu_out_ena # some are enabled 1553 1554fu_out_done: 1555 1556 mov.l EXC_A6(%a6),(%a6) # in case a6 changed 1557 1558# on extended precision opclass three instructions using pre-decrement or 1559# post-increment addressing mode, the address register is not updated. is the 1560# address register was the stack pointer used from user mode, then let's update 1561# it here. if it was used from supervisor mode, then we have to handle this 1562# as a special case. 1563 btst &0x5,EXC_SR(%a6) 1564 bne.b fu_out_done_s 1565 1566 mov.l EXC_A7(%a6),%a0 # restore a7 1567 mov.l %a0,%usp 1568 1569fu_out_done_cont: 1570 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1571 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1572 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1573 1574 unlk %a6 1575 1576 btst &0x7,(%sp) # is trace on? 1577 bne.b fu_out_trace # yes 1578 1579 bra.l _fpsp_done 1580 1581# is the ea mode pre-decrement of the stack pointer from supervisor mode? 1582# ("fmov.x fpm,-(a7)") if so, 1583fu_out_done_s: 1584 cmpi.b SPCOND_FLG(%a6),&mda7_flg 1585 bne.b fu_out_done_cont 1586 1587# the extended precision result is still in fp0. but, we need to save it 1588# somewhere on the stack until we can copy it to its final resting place. 1589# here, we're counting on the top of the stack to be the old place-holders 1590# for fp0/fp1 which have already been restored. that way, we can write 1591# over those destinations with the shifted stack frame. 1592 fmovm.x &0x80,FP_SRC(%a6) # put answer on stack 1593 1594 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1595 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1596 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1597 1598 mov.l (%a6),%a6 # restore frame pointer 1599 1600 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) 1601 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp) 1602 1603# now, copy the result to the proper place on the stack 1604 mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp) 1605 mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp) 1606 mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp) 1607 1608 add.l &LOCAL_SIZE-0x8,%sp 1609 1610 btst &0x7,(%sp) 1611 bne.b fu_out_trace 1612 1613 bra.l _fpsp_done 1614 1615fu_out_ena: 1616 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled 1617 bfffo %d0{&24:&8},%d0 # find highest priority exception 1618 bne.b fu_out_exc # there is at least one set 1619 1620# no exceptions were set. 1621# if a disabled overflow occurred and inexact was enabled but the result 1622# was exact, then a branch to _real_inex() is made. 1623 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set? 1624 beq.w fu_out_done # no 1625 1626fu_out_ovflchk: 1627 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled? 1628 beq.w fu_out_done # no 1629 bra.w fu_inex # yes 1630 1631# 1632# The fp move out that took the "Unimplemented Data Type" exception was 1633# being traced. Since the stack frames are similar, get the "current" PC 1634# from FPIAR and put it in the trace stack frame then jump to _real_trace(). 1635# 1636# UNSUPP FRAME TRACE FRAME 1637# ***************** ***************** 1638# * EA * * Current * 1639# * * * PC * 1640# ***************** ***************** 1641# * 0x3 * 0x0dc * * 0x2 * 0x024 * 1642# ***************** ***************** 1643# * Next * * Next * 1644# * PC * * PC * 1645# ***************** ***************** 1646# * SR * * SR * 1647# ***************** ***************** 1648# 1649fu_out_trace: 1650 mov.w &0x2024,0x6(%sp) 1651 fmov.l %fpiar,0x8(%sp) 1652 bra.l _real_trace 1653 1654# an exception occurred and that exception was enabled. 1655fu_out_exc: 1656 subi.l &24,%d0 # fix offset to be 0-8 1657 1658# we don't mess with the existing fsave frame. just re-insert it and 1659# jump to the "_real_{}()" handler... 1660 mov.w (tbl_fu_out.b,%pc,%d0.w*2),%d0 1661 jmp (tbl_fu_out.b,%pc,%d0.w*1) 1662 1663 swbeg &0x8 1664tbl_fu_out: 1665 short tbl_fu_out - tbl_fu_out # BSUN can't happen 1666 short tbl_fu_out - tbl_fu_out # SNAN can't happen 1667 short fu_operr - tbl_fu_out # OPERR 1668 short fu_ovfl - tbl_fu_out # OVFL 1669 short fu_unfl - tbl_fu_out # UNFL 1670 short tbl_fu_out - tbl_fu_out # DZ can't happen 1671 short fu_inex - tbl_fu_out # INEX2 1672 short tbl_fu_out - tbl_fu_out # INEX1 won't make it here 1673 1674# for snan,operr,ovfl,unfl, src op is still in FP_SRC so just 1675# frestore it. 1676fu_snan: 1677 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1678 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1679 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1680 1681 mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd8 1682 mov.w &0xe006,2+FP_SRC(%a6) 1683 1684 frestore FP_SRC(%a6) 1685 1686 unlk %a6 1687 1688 1689 bra.l _real_snan 1690 1691fu_operr: 1692 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1693 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1694 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1695 1696 mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0 1697 mov.w &0xe004,2+FP_SRC(%a6) 1698 1699 frestore FP_SRC(%a6) 1700 1701 unlk %a6 1702 1703 1704 bra.l _real_operr 1705 1706fu_ovfl: 1707 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack 1708 1709 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1710 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1711 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1712 1713 mov.w &0x30d4,EXC_VOFF(%a6) # vector offset = 0xd4 1714 mov.w &0xe005,2+FP_SRC(%a6) 1715 1716 frestore FP_SRC(%a6) # restore EXOP 1717 1718 unlk %a6 1719 1720 bra.l _real_ovfl 1721 1722# underflow can happen for extended precision. extended precision opclass 1723# three instruction exceptions don't update the stack pointer. so, if the 1724# exception occurred from user mode, then simply update a7 and exit normally. 1725# if the exception occurred from supervisor mode, check if 1726fu_unfl: 1727 mov.l EXC_A6(%a6),(%a6) # restore a6 1728 1729 btst &0x5,EXC_SR(%a6) 1730 bne.w fu_unfl_s 1731 1732 mov.l EXC_A7(%a6),%a0 # restore a7 whether we need 1733 mov.l %a0,%usp # to or not... 1734 1735fu_unfl_cont: 1736 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack 1737 1738 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1739 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1740 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1741 1742 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc 1743 mov.w &0xe003,2+FP_SRC(%a6) 1744 1745 frestore FP_SRC(%a6) # restore EXOP 1746 1747 unlk %a6 1748 1749 bra.l _real_unfl 1750 1751fu_unfl_s: 1752 cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)? 1753 bne.b fu_unfl_cont 1754 1755# the extended precision result is still in fp0. but, we need to save it 1756# somewhere on the stack until we can copy it to its final resting place 1757# (where the exc frame is currently). make sure it's not at the top of the 1758# frame or it will get overwritten when the exc stack frame is shifted "down". 1759 fmovm.x &0x80,FP_SRC(%a6) # put answer on stack 1760 fmovm.x &0x40,FP_DST(%a6) # put EXOP on stack 1761 1762 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1763 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1764 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1765 1766 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc 1767 mov.w &0xe003,2+FP_DST(%a6) 1768 1769 frestore FP_DST(%a6) # restore EXOP 1770 1771 mov.l (%a6),%a6 # restore frame pointer 1772 1773 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) 1774 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp) 1775 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp) 1776 1777# now, copy the result to the proper place on the stack 1778 mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp) 1779 mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp) 1780 mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp) 1781 1782 add.l &LOCAL_SIZE-0x8,%sp 1783 1784 bra.l _real_unfl 1785 1786# fmove in and out enter here. 1787fu_inex: 1788 fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack 1789 1790 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1791 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1792 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1793 1794 mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4 1795 mov.w &0xe001,2+FP_SRC(%a6) 1796 1797 frestore FP_SRC(%a6) # restore EXOP 1798 1799 unlk %a6 1800 1801 1802 bra.l _real_inex 1803 1804######################################################################### 1805######################################################################### 1806fu_in_pack: 1807 1808 1809# I'm not sure at this point what FPSR bits are valid for this instruction. 1810# so, since the emulation routines re-create them anyways, zero exception field 1811 andi.l &0x0ff00ff,USER_FPSR(%a6) # zero exception field 1812 1813 fmov.l &0x0,%fpcr # zero current control regs 1814 fmov.l &0x0,%fpsr 1815 1816 bsr.l get_packed # fetch packed src operand 1817 1818 lea FP_SRC(%a6),%a0 # pass ptr to src 1819 bsr.l set_tag_x # set src optype tag 1820 1821 mov.b %d0,STAG(%a6) # save src optype tag 1822 1823 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg 1824 1825# bit five of the fp extension word separates the monadic and dyadic operations 1826# at this point 1827 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic? 1828 beq.b fu_extract_p # monadic 1829 cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst? 1830 beq.b fu_extract_p # yes, so it's monadic, too 1831 1832 bsr.l load_fpn2 # load dst into FP_DST 1833 1834 lea FP_DST(%a6),%a0 # pass: ptr to dst op 1835 bsr.l set_tag_x # tag the operand type 1836 cmpi.b %d0,&UNNORM # is operand an UNNORM? 1837 bne.b fu_op2_done_p # no 1838 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO 1839fu_op2_done_p: 1840 mov.b %d0,DTAG(%a6) # save dst optype tag 1841 1842fu_extract_p: 1843 clr.l %d0 1844 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec 1845 1846 bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension 1847 1848 lea FP_SRC(%a6),%a0 1849 lea FP_DST(%a6),%a1 1850 1851 mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr 1852 jsr (tbl_unsupp.l,%pc,%d1.l*1) 1853 1854# 1855# Exceptions in order of precedence: 1856# BSUN : none 1857# SNAN : all dyadic ops 1858# OPERR : fsqrt(-NORM) 1859# OVFL : all except ftst,fcmp 1860# UNFL : all except ftst,fcmp 1861# DZ : fdiv 1862# INEX2 : all except ftst,fcmp 1863# INEX1 : all 1864# 1865 1866# we determine the highest priority exception(if any) set by the 1867# emulation routine that has also been enabled by the user. 1868 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled 1869 bne.w fu_in_ena_p # some are enabled 1870 1871fu_in_cont_p: 1872# fcmp and ftst do not store any result. 1873 mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension 1874 andi.b &0x38,%d0 # extract bits 3-5 1875 cmpi.b %d0,&0x38 # is instr fcmp or ftst? 1876 beq.b fu_in_exit_p # yes 1877 1878 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg 1879 bsr.l store_fpreg # store the result 1880 1881fu_in_exit_p: 1882 1883 btst &0x5,EXC_SR(%a6) # user or supervisor? 1884 bne.w fu_in_exit_s_p # supervisor 1885 1886 mov.l EXC_A7(%a6),%a0 # update user a7 1887 mov.l %a0,%usp 1888 1889fu_in_exit_cont_p: 1890 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1891 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1892 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1893 1894 unlk %a6 # unravel stack frame 1895 1896 btst &0x7,(%sp) # is trace on? 1897 bne.w fu_trace_p # yes 1898 1899 bra.l _fpsp_done # exit to os 1900 1901# the exception occurred in supervisor mode. check to see if the 1902# addressing mode was (a7)+. if so, we'll need to shift the 1903# stack frame "up". 1904fu_in_exit_s_p: 1905 btst &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+ 1906 beq.b fu_in_exit_cont_p # no 1907 1908 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1909 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1910 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1911 1912 unlk %a6 # unravel stack frame 1913 1914# shift the stack frame "up". we don't really care about the <ea> field. 1915 mov.l 0x4(%sp),0x10(%sp) 1916 mov.l 0x0(%sp),0xc(%sp) 1917 add.l &0xc,%sp 1918 1919 btst &0x7,(%sp) # is trace on? 1920 bne.w fu_trace_p # yes 1921 1922 bra.l _fpsp_done # exit to os 1923 1924fu_in_ena_p: 1925 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled & set 1926 bfffo %d0{&24:&8},%d0 # find highest priority exception 1927 bne.b fu_in_exc_p # at least one was set 1928 1929# 1930# No exceptions occurred that were also enabled. Now: 1931# 1932# if (OVFL && ovfl_disabled && inexact_enabled) { 1933# branch to _real_inex() (even if the result was exact!); 1934# } else { 1935# save the result in the proper fp reg (unless the op is fcmp or ftst); 1936# return; 1937# } 1938# 1939 btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set? 1940 beq.w fu_in_cont_p # no 1941 1942fu_in_ovflchk_p: 1943 btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled? 1944 beq.w fu_in_cont_p # no 1945 bra.w fu_in_exc_ovfl_p # do _real_inex() now 1946 1947# 1948# An exception occurred and that exception was enabled: 1949# 1950# shift enabled exception field into lo byte of d0; 1951# if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) || 1952# ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) { 1953# /* 1954# * this is the case where we must call _real_inex() now or else 1955# * there will be no other way to pass it the exceptional operand 1956# */ 1957# call _real_inex(); 1958# } else { 1959# restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU; 1960# } 1961# 1962fu_in_exc_p: 1963 subi.l &24,%d0 # fix offset to be 0-8 1964 cmpi.b %d0,&0x6 # is exception INEX? (6 or 7) 1965 blt.b fu_in_exc_exit_p # no 1966 1967# the enabled exception was inexact 1968 btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur? 1969 bne.w fu_in_exc_unfl_p # yes 1970 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur? 1971 bne.w fu_in_exc_ovfl_p # yes 1972 1973# here, we insert the correct fsave status value into the fsave frame for the 1974# corresponding exception. the operand in the fsave frame should be the original 1975# src operand. 1976# as a reminder for future predicted pain and agony, we are passing in fsave the 1977# "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs. 1978# this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!! 1979fu_in_exc_exit_p: 1980 btst &0x5,EXC_SR(%a6) # user or supervisor? 1981 bne.w fu_in_exc_exit_s_p # supervisor 1982 1983 mov.l EXC_A7(%a6),%a0 # update user a7 1984 mov.l %a0,%usp 1985 1986fu_in_exc_exit_cont_p: 1987 mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6) 1988 1989 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 1990 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 1991 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 1992 1993 frestore FP_SRC(%a6) # restore src op 1994 1995 unlk %a6 1996 1997 btst &0x7,(%sp) # is trace enabled? 1998 bne.w fu_trace_p # yes 1999 2000 bra.l _fpsp_done
2001 2002tbl_except_p: 2003 short 0xe000,0xe006,0xe004,0xe005 2004 short 0xe003,0xe002,0xe001,0xe001 2005 2006fu_in_exc_ovfl_p: 2007 mov.w &0x3,%d0 2008 bra.w fu_in_exc_exit_p 2009 2010fu_in_exc_unfl_p: 2011 mov.w &0x4,%d0 2012 bra.w fu_in_exc_exit_p 2013 2014fu_in_exc_exit_s_p: 2015 btst &mia7_bit,SPCOND_FLG(%a6) 2016 beq.b fu_in_exc_exit_cont_p 2017 2018 mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6) 2019 2020 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 2021 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2022 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2023 2024 frestore FP_SRC(%a6) # restore src op 2025 2026 unlk %a6 # unravel stack frame 2027 2028# shift stack frame "up". who cares about <ea> field. 2029 mov.l 0x4(%sp),0x10(%sp) 2030 mov.l 0x0(%sp),0xc(%sp) 2031 add.l &0xc,%sp 2032 2033 btst &0x7,(%sp) # is trace on? 2034 bne.b fu_trace_p # yes 2035 2036 bra.l _fpsp_done # exit to os 2037 2038# 2039# The opclass two PACKED instruction that took an "Unimplemented Data Type" 2040# exception was being traced. Make the "current" PC the FPIAR and put it in the 2041# trace stack frame then jump to _real_trace(). 2042# 2043# UNSUPP FRAME TRACE FRAME 2044# ***************** ***************** 2045# * EA * * Current * 2046# * * * PC * 2047# ***************** ***************** 2048# * 0x2 * 0x0dc * * 0x2 * 0x024 * 2049# ***************** ***************** 2050# * Next * * Next * 2051# * PC * * PC * 2052# ***************** ***************** 2053# * SR * * SR * 2054# ***************** ***************** 2055fu_trace_p: 2056 mov.w &0x2024,0x6(%sp) 2057 fmov.l %fpiar,0x8(%sp) 2058 2059 bra.l _real_trace 2060 2061######################################################### 2062######################################################### 2063fu_out_pack: 2064 2065 2066# I'm not sure at this point what FPSR bits are valid for this instruction. 2067# so, since the emulation routines re-create them anyways, zero exception field. 2068# fmove out doesn't affect ccodes. 2069 and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field 2070 2071 fmov.l &0x0,%fpcr # zero current control regs 2072 fmov.l &0x0,%fpsr 2073 2074 bfextu EXC_CMDREG(%a6){&6:&3},%d0 2075 bsr.l load_fpn1 2076 2077# unlike other opclass 3, unimplemented data type exceptions, packed must be 2078# able to detect all operand types. 2079 lea FP_SRC(%a6),%a0 2080 bsr.l set_tag_x # tag the operand type 2081 cmpi.b %d0,&UNNORM # is operand an UNNORM? 2082 bne.b fu_op2_p # no 2083 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO 2084 2085fu_op2_p: 2086 mov.b %d0,STAG(%a6) # save src optype tag 2087 2088 clr.l %d0 2089 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec 2090 2091 lea FP_SRC(%a6),%a0 # pass ptr to src operand 2092 2093 mov.l (%a6),EXC_A6(%a6) # in case a6 changes 2094 bsr.l fout # call fmove out routine 2095 2096# Exceptions in order of precedence: 2097# BSUN : no 2098# SNAN : yes 2099# OPERR : if ((k_factor > +17) || (dec. exp exceeds 3 digits)) 2100# OVFL : no 2101# UNFL : no 2102# DZ : no 2103# INEX2 : yes 2104# INEX1 : no 2105 2106# determine the highest priority exception(if any) set by the 2107# emulation routine that has also been enabled by the user. 2108 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled 2109 bne.w fu_out_ena_p # some are enabled 2110 2111fu_out_exit_p: 2112 mov.l EXC_A6(%a6),(%a6) # restore a6 2113 2114 btst &0x5,EXC_SR(%a6) # user or supervisor? 2115 bne.b fu_out_exit_s_p # supervisor 2116 2117 mov.l EXC_A7(%a6),%a0 # update user a7 2118 mov.l %a0,%usp 2119 2120fu_out_exit_cont_p: 2121 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 2122 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2123 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2124 2125 unlk %a6 # unravel stack frame 2126 2127 btst &0x7,(%sp) # is trace on? 2128 bne.w fu_trace_p # yes 2129 2130 bra.l _fpsp_done # exit to os 2131 2132# the exception occurred in supervisor mode. check to see if the 2133# addressing mode was -(a7). if so, we'll need to shift the 2134# stack frame "down". 2135fu_out_exit_s_p: 2136 btst &mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7) 2137 beq.b fu_out_exit_cont_p # no 2138 2139 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 2140 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2141 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2142 2143 mov.l (%a6),%a6 # restore frame pointer 2144 2145 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) 2146 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp) 2147 2148# now, copy the result to the proper place on the stack 2149 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp) 2150 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp) 2151 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp) 2152 2153 add.l &LOCAL_SIZE-0x8,%sp 2154 2155 btst &0x7,(%sp) 2156 bne.w fu_trace_p 2157 2158 bra.l _fpsp_done 2159 2160fu_out_ena_p: 2161 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled 2162 bfffo %d0{&24:&8},%d0 # find highest priority exception 2163 beq.w fu_out_exit_p 2164 2165 mov.l EXC_A6(%a6),(%a6) # restore a6 2166 2167# an exception occurred and that exception was enabled. 2168# the only exception possible on packed move out are INEX, OPERR, and SNAN. 2169fu_out_exc_p: 2170 cmpi.b %d0,&0x1a 2171 bgt.w fu_inex_p2 2172 beq.w fu_operr_p 2173 2174fu_snan_p: 2175 btst &0x5,EXC_SR(%a6) 2176 bne.b fu_snan_s_p 2177 2178 mov.l EXC_A7(%a6),%a0 2179 mov.l %a0,%usp 2180 bra.w fu_snan 2181 2182fu_snan_s_p: 2183 cmpi.b SPCOND_FLG(%a6),&mda7_flg 2184 bne.w fu_snan 2185 2186# the instruction was "fmove.p fpn,-(a7)" from supervisor mode. 2187# the strategy is to move the exception frame "down" 12 bytes. then, we 2188# can store the default result where the exception frame was. 2189 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 2190 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2191 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2192 2193 mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd0 2194 mov.w &0xe006,2+FP_SRC(%a6) # set fsave status 2195 2196 frestore FP_SRC(%a6) # restore src operand 2197 2198 mov.l (%a6),%a6 # restore frame pointer 2199 2200 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) 2201 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp) 2202 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp) 2203 2204# now, we copy the default result to its proper location 2205 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp) 2206 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp) 2207 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp) 2208 2209 add.l &LOCAL_SIZE-0x8,%sp 2210 2211 2212 bra.l _real_snan 2213 2214fu_operr_p: 2215 btst &0x5,EXC_SR(%a6) 2216 bne.w fu_operr_p_s 2217 2218 mov.l EXC_A7(%a6),%a0 2219 mov.l %a0,%usp 2220 bra.w fu_operr 2221 2222fu_operr_p_s: 2223 cmpi.b SPCOND_FLG(%a6),&mda7_flg 2224 bne.w fu_operr 2225 2226# the instruction was "fmove.p fpn,-(a7)" from supervisor mode. 2227# the strategy is to move the exception frame "down" 12 bytes. then, we 2228# can store the default result where the exception frame was. 2229 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 2230 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2231 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2232 2233 mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0 2234 mov.w &0xe004,2+FP_SRC(%a6) # set fsave status 2235 2236 frestore FP_SRC(%a6) # restore src operand 2237 2238 mov.l (%a6),%a6 # restore frame pointer 2239 2240 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) 2241 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp) 2242 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp) 2243 2244# now, we copy the default result to its proper location 2245 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp) 2246 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp) 2247 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp) 2248 2249 add.l &LOCAL_SIZE-0x8,%sp 2250 2251 2252 bra.l _real_operr 2253 2254fu_inex_p2: 2255 btst &0x5,EXC_SR(%a6) 2256 bne.w fu_inex_s_p2 2257 2258 mov.l EXC_A7(%a6),%a0 2259 mov.l %a0,%usp 2260 bra.w fu_inex 2261 2262fu_inex_s_p2: 2263 cmpi.b SPCOND_FLG(%a6),&mda7_flg 2264 bne.w fu_inex 2265 2266# the instruction was "fmove.p fpn,-(a7)" from supervisor mode. 2267# the strategy is to move the exception frame "down" 12 bytes. then, we 2268# can store the default result where the exception frame was. 2269 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1 2270 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2271 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2272 2273 mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4 2274 mov.w &0xe001,2+FP_SRC(%a6) # set fsave status 2275 2276 frestore FP_SRC(%a6) # restore src operand 2277 2278 mov.l (%a6),%a6 # restore frame pointer 2279 2280 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) 2281 mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp) 2282 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp) 2283 2284# now, we copy the default result to its proper location 2285 mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp) 2286 mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp) 2287 mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp) 2288 2289 add.l &LOCAL_SIZE-0x8,%sp 2290 2291 2292 bra.l _real_inex 2293 2294######################################################################### 2295 2296# 2297# if we're stuffing a source operand back into an fsave frame then we 2298# have to make sure that for single or double source operands that the 2299# format stuffed is as weird as the hardware usually makes it. 2300# 2301 global funimp_skew 2302funimp_skew: 2303 bfextu EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier 2304 cmpi.b %d0,&0x1 # was src sgl? 2305 beq.b funimp_skew_sgl # yes 2306 cmpi.b %d0,&0x5 # was src dbl? 2307 beq.b funimp_skew_dbl # yes 2308 rts 2309 2310funimp_skew_sgl: 2311 mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent 2312 andi.w &0x7fff,%d0 # strip sign 2313 beq.b funimp_skew_sgl_not 2314 cmpi.w %d0,&0x3f80 2315 bgt.b funimp_skew_sgl_not 2316 neg.w %d0 # make exponent negative 2317 addi.w &0x3f81,%d0 # find amt to shift 2318 mov.l FP_SRC_HI(%a6),%d1 # fetch DENORM hi(man) 2319 lsr.l %d0,%d1 # shift it 2320 bset &31,%d1 # set j-bit 2321 mov.l %d1,FP_SRC_HI(%a6) # insert new hi(man) 2322 andi.w &0x8000,FP_SRC_EX(%a6) # clear old exponent 2323 ori.w &0x3f80,FP_SRC_EX(%a6) # insert new "skewed" exponent 2324funimp_skew_sgl_not: 2325 rts 2326 2327funimp_skew_dbl: 2328 mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent 2329 andi.w &0x7fff,%d0 # strip sign 2330 beq.b funimp_skew_dbl_not 2331 cmpi.w %d0,&0x3c00 2332 bgt.b funimp_skew_dbl_not 2333 2334 tst.b FP_SRC_EX(%a6) # make "internal format" 2335 smi.b 0x2+FP_SRC(%a6) 2336 mov.w %d0,FP_SRC_EX(%a6) # insert exponent with cleared sign 2337 clr.l %d0 # clear g,r,s 2338 lea FP_SRC(%a6),%a0 # pass ptr to src op 2339 mov.w &0x3c01,%d1 # pass denorm threshold 2340 bsr.l dnrm_lp # denorm it 2341 mov.w &0x3c00,%d0 # new exponent 2342 tst.b 0x2+FP_SRC(%a6) # is sign set? 2343 beq.b fss_dbl_denorm_done # no 2344 bset &15,%d0 # set sign 2345fss_dbl_denorm_done: 2346 bset &0x7,FP_SRC_HI(%a6) # set j-bit 2347 mov.w %d0,FP_SRC_EX(%a6) # insert new exponent 2348funimp_skew_dbl_not: 2349 rts 2350 2351######################################################################### 2352 global _mem_write2 2353_mem_write2: 2354 btst &0x5,EXC_SR(%a6) 2355 beq.l _dmem_write 2356 mov.l 0x0(%a0),FP_DST_EX(%a6) 2357 mov.l 0x4(%a0),FP_DST_HI(%a6) 2358 mov.l 0x8(%a0),FP_DST_LO(%a6) 2359 clr.l %d1 2360 rts 2361 2362######################################################################### 2363# XDEF **************************************************************** # 2364# _fpsp_effadd(): 060FPSP entry point for FP "Unimplemented # 2365# effective address" exception. # 2366# # 2367# This handler should be the first code executed upon taking the # 2368# FP Unimplemented Effective Address exception in an operating # 2369# system. # 2370# # 2371# XREF **************************************************************** # 2372# _imem_read_long() - read instruction longword # 2373# fix_skewed_ops() - adjust src operand in fsave frame # 2374# set_tag_x() - determine optype of src/dst operands # 2375# store_fpreg() - store opclass 0 or 2 result to FP regfile # 2376# unnorm_fix() - change UNNORM operands to NORM or ZERO # 2377# load_fpn2() - load dst operand from FP regfile # 2378# tbl_unsupp - add of table of emulation routines for opclass 0,2 # 2379# decbin() - convert packed data to FP binary data # 2380# _real_fpu_disabled() - "callout" for "FPU disabled" exception # 2381# _real_access() - "callout" for access error exception # 2382# _mem_read() - read extended immediate operand from memory # 2383# _fpsp_done() - "callout" for exit; work all done # 2384# _real_trace() - "callout" for Trace enabled exception # 2385# fmovm_dynamic() - emulate dynamic fmovm instruction # 2386# fmovm_ctrl() - emulate fmovm control instruction # 2387# # 2388# INPUT *************************************************************** # 2389# - The system stack contains the "Unimplemented <ea>" stk frame # 2390# # 2391# OUTPUT ************************************************************** # 2392# If access error: # 2393# - The system stack is changed to an access error stack frame # 2394# If FPU disabled: # 2395# - The system stack is changed to an FPU disabled stack frame # 2396# If Trace exception enabled: # 2397# - The system stack is changed to a Trace exception stack frame # 2398# Else: (normal case) # 2399# - None (correct result has been stored as appropriate) # 2400# # 2401# ALGORITHM *********************************************************** # 2402# This exception handles 3 types of operations: # 2403# (1) FP Instructions using extended precision or packed immediate # 2404# addressing mode. # 2405# (2) The "fmovm.x" instruction w/ dynamic register specification. # 2406# (3) The "fmovm.l" instruction w/ 2 or 3 control registers. # 2407# # 2408# For immediate data operations, the data is read in w/ a # 2409# _mem_read() "callout", converted to FP binary (if packed), and used # 2410# as the source operand to the instruction specified by the instruction # 2411# word. If no FP exception should be reported ads a result of the # 2412# emulation, then the result is stored to the destination register and # 2413# the handler exits through _fpsp_done(). If an enabled exc has been # 2414# signalled as a result of emulation, then an fsave state frame # 2415# corresponding to the FP exception type must be entered into the 060 # 2416# FPU before exiting. In either the enabled or disabled cases, we # 2417# must also check if a Trace exception is pending, in which case, we # 2418# must create a Trace exception stack frame from the current exception # 2419# stack frame. If no Trace is pending, we simply exit through # 2420# _fpsp_done(). # 2421# For "fmovm.x", call the routine fmovm_dynamic() which will # 2422# decode and emulate the instruction. No FP exceptions can be pending # 2423# as a result of this operation emulation. A Trace exception can be # 2424# pending, though, which means the current stack frame must be changed # 2425# to a Trace stack frame and an exit made through _real_trace(). # 2426# For the case of "fmovm.x Dn,-(a7)", where the offending instruction # 2427# was executed from supervisor mode, this handler must store the FP # 2428# register file values to the system stack by itself since # 2429# fmovm_dynamic() can't handle this. A normal exit is made through # 2430# fpsp_done(). # 2431# For "fmovm.l", fmovm_ctrl() is used to emulate the instruction. # 2432# Again, a Trace exception may be pending and an exit made through # 2433# _real_trace(). Else, a normal exit is made through _fpsp_done(). # 2434# # 2435# Before any of the above is attempted, it must be checked to # 2436# see if the FPU is disabled. Since the "Unimp <ea>" exception is taken # 2437# before the "FPU disabled" exception, but the "FPU disabled" exception # 2438# has higher priority, we check the disabled bit in the PCR. If set, # 2439# then we must create an 8 word "FPU disabled" exception stack frame # 2440# from the current 4 word exception stack frame. This includes # 2441# reproducing the effective address of the instruction to put on the # 2442# new stack frame. # 2443# # 2444# In the process of all emulation work, if a _mem_read() # 2445# "callout" returns a failing result indicating an access error, then # 2446# we must create an access error stack frame from the current stack # 2447# frame. This information includes a faulting address and a fault- # 2448# status-longword. These are created within this handler. # 2449# # 2450######################################################################### 2451 2452 global _fpsp_effadd 2453_fpsp_effadd: 2454 2455# This exception type takes priority over the "Line F Emulator" 2456# exception. Therefore, the FPU could be disabled when entering here. 2457# So, we must check to see if it's disabled and handle that case separately. 2458 mov.l %d0,-(%sp) # save d0 2459 movc %pcr,%d0 # load proc cr 2460 btst &0x1,%d0 # is FPU disabled? 2461 bne.w iea_disabled # yes 2462 mov.l (%sp)+,%d0 # restore d0 2463 2464 link %a6,&-LOCAL_SIZE # init stack frame 2465 2466 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 2467 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 2468 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 2469 2470# PC of instruction that took the exception is the PC in the frame 2471 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6) 2472 2473 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 2474 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 2475 bsr.l _imem_read_long # fetch the instruction words 2476 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD 2477 2478######################################################################### 2479 2480 tst.w %d0 # is operation fmovem? 2481 bmi.w iea_fmovm # yes 2482 2483# 2484# here, we will have: 2485# fabs fdabs fsabs facos fmod 2486# fadd fdadd fsadd fasin frem 2487# fcmp fatan fscale 2488# fdiv fddiv fsdiv fatanh fsin 2489# fint fcos fsincos 2490# fintrz fcosh fsinh 2491# fmove fdmove fsmove fetox ftan 2492# fmul fdmul fsmul fetoxm1 ftanh 2493# fneg fdneg fsneg fgetexp ftentox 2494# fsgldiv fgetman ftwotox 2495# fsglmul flog10 2496# fsqrt flog2 2497# fsub fdsub fssub flogn 2498# ftst flognp1 2499# which can all use f<op>.{x,p} 2500# so, now it's immediate data extended precision AND PACKED FORMAT! 2501# 2502iea_op: 2503 andi.l &0x00ff00ff,USER_FPSR(%a6) 2504 2505 btst &0xa,%d0 # is src fmt x or p? 2506 bne.b iea_op_pack # packed 2507 2508 2509 mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data> 2510 lea FP_SRC(%a6),%a1 # pass: ptr to super addr 2511 mov.l &0xc,%d0 # pass: 12 bytes 2512 bsr.l _imem_read # read extended immediate 2513 2514 tst.l %d1 # did ifetch fail? 2515 bne.w iea_iacc # yes 2516 2517 bra.b iea_op_setsrc 2518 2519iea_op_pack: 2520 2521 mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data> 2522 lea FP_SRC(%a6),%a1 # pass: ptr to super dst 2523 mov.l &0xc,%d0 # pass: 12 bytes 2524 bsr.l _imem_read # read packed operand 2525 2526 tst.l %d1 # did ifetch fail? 2527 bne.w iea_iacc # yes 2528 2529# The packed operand is an INF or a NAN if the exponent field is all ones. 2530 bfextu FP_SRC(%a6){&1:&15},%d0 # get exp 2531 cmpi.w %d0,&0x7fff # INF or NAN? 2532 beq.b iea_op_setsrc # operand is an INF or NAN 2533 2534# The packed operand is a zero if the mantissa is all zero, else it's 2535# a normal packed op. 2536 mov.b 3+FP_SRC(%a6),%d0 # get byte 4 2537 andi.b &0x0f,%d0 # clear all but last nybble 2538 bne.b iea_op_gp_not_spec # not a zero 2539 tst.l FP_SRC_HI(%a6) # is lw 2 zero? 2540 bne.b iea_op_gp_not_spec # not a zero 2541 tst.l FP_SRC_LO(%a6) # is lw 3 zero? 2542 beq.b iea_op_setsrc # operand is a ZERO 2543iea_op_gp_not_spec: 2544 lea FP_SRC(%a6),%a0 # pass: ptr to packed op 2545 bsr.l decbin # convert to extended 2546 fmovm.x &0x80,FP_SRC(%a6) # make this the srcop 2547 2548iea_op_setsrc: 2549 addi.l &0xc,EXC_EXTWPTR(%a6) # update extension word pointer 2550 2551# FP_SRC now holds the src operand. 2552 lea FP_SRC(%a6),%a0 # pass: ptr to src op 2553 bsr.l set_tag_x # tag the operand type 2554 mov.b %d0,STAG(%a6) # could be ANYTHING!!! 2555 cmpi.b %d0,&UNNORM # is operand an UNNORM? 2556 bne.b iea_op_getdst # no 2557 bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO 2558 mov.b %d0,STAG(%a6) # set new optype tag 2559iea_op_getdst: 2560 clr.b STORE_FLG(%a6) # clear "store result" boolean 2561 2562 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic? 2563 beq.b iea_op_extract # monadic 2564 btst &0x4,1+EXC_CMDREG(%a6) # is operation fsincos,ftst,fcmp? 2565 bne.b iea_op_spec # yes 2566 2567iea_op_loaddst: 2568 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno 2569 bsr.l load_fpn2 # load dst operand 2570 2571 lea FP_DST(%a6),%a0 # pass: ptr to dst op 2572 bsr.l set_tag_x # tag the operand type 2573 mov.b %d0,DTAG(%a6) # could be ANYTHING!!! 2574 cmpi.b %d0,&UNNORM # is operand an UNNORM? 2575 bne.b iea_op_extract # no 2576 bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO 2577 mov.b %d0,DTAG(%a6) # set new optype tag 2578 bra.b iea_op_extract 2579 2580# the operation is fsincos, ftst, or fcmp. only fcmp is dyadic 2581iea_op_spec: 2582 btst &0x3,1+EXC_CMDREG(%a6) # is operation fsincos? 2583 beq.b iea_op_extract # yes 2584# now, we're left with ftst and fcmp. so, first let's tag them so that they don't 2585# store a result. then, only fcmp will branch back and pick up a dst operand. 2586 st STORE_FLG(%a6) # don't store a final result 2587 btst &0x1,1+EXC_CMDREG(%a6) # is operation fcmp? 2588 beq.b iea_op_loaddst # yes 2589 2590iea_op_extract: 2591 clr.l %d0 2592 mov.b FPCR_MODE(%a6),%d0 # pass: rnd mode,prec 2593 2594 mov.b 1+EXC_CMDREG(%a6),%d1 2595 andi.w &0x007f,%d1 # extract extension 2596 2597 fmov.l &0x0,%fpcr 2598 fmov.l &0x0,%fpsr 2599 2600 lea FP_SRC(%a6),%a0 2601 lea FP_DST(%a6),%a1 2602 2603 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr 2604 jsr (tbl_unsupp.l,%pc,%d1.l*1) 2605 2606# 2607# Exceptions in order of precedence: 2608# BSUN : none 2609# SNAN : all operations 2610# OPERR : all reg-reg or mem-reg operations that can normally operr 2611# OVFL : same as OPERR 2612# UNFL : same as OPERR 2613# DZ : same as OPERR 2614# INEX2 : same as OPERR 2615# INEX1 : all packed immediate operations 2616# 2617 2618# we determine the highest priority exception(if any) set by the 2619# emulation routine that has also been enabled by the user. 2620 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled 2621 bne.b iea_op_ena # some are enabled 2622 2623# now, we save the result, unless, of course, the operation was ftst or fcmp. 2624# these don't save results. 2625iea_op_save: 2626 tst.b STORE_FLG(%a6) # does this op store a result? 2627 bne.b iea_op_exit1 # exit with no frestore 2628 2629iea_op_store: 2630 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno 2631 bsr.l store_fpreg # store the result 2632 2633iea_op_exit1: 2634 mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC" 2635 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame 2636 2637 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 2638 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2639 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2640 2641 unlk %a6 # unravel the frame 2642 2643 btst &0x7,(%sp) # is trace on? 2644 bne.w iea_op_trace # yes 2645 2646 bra.l _fpsp_done # exit to os 2647 2648iea_op_ena: 2649 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enable and set 2650 bfffo %d0{&24:&8},%d0 # find highest priority exception 2651 bne.b iea_op_exc # at least one was set 2652 2653# no exception occurred. now, did a disabled, exact overflow occur with inexact 2654# enabled? if so, then we have to stuff an overflow frame into the FPU. 2655 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur? 2656 beq.b iea_op_save 2657 2658iea_op_ovfl: 2659 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled? 2660 beq.b iea_op_store # no 2661 bra.b iea_op_exc_ovfl # yes 2662 2663# an enabled exception occurred. we have to insert the exception type back into 2664# the machine. 2665iea_op_exc: 2666 subi.l &24,%d0 # fix offset to be 0-8 2667 cmpi.b %d0,&0x6 # is exception INEX? 2668 bne.b iea_op_exc_force # no 2669 2670# the enabled exception was inexact. so, if it occurs with an overflow 2671# or underflow that was disabled, then we have to force an overflow or 2672# underflow frame. 2673 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur? 2674 bne.b iea_op_exc_ovfl # yes 2675 btst &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur? 2676 bne.b iea_op_exc_unfl # yes 2677 2678iea_op_exc_force: 2679 mov.w (tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) 2680 bra.b iea_op_exit2 # exit with frestore 2681 2682tbl_iea_except: 2683 short 0xe002, 0xe006, 0xe004, 0xe005 2684 short 0xe003, 0xe002, 0xe001, 0xe001 2685 2686iea_op_exc_ovfl: 2687 mov.w &0xe005,2+FP_SRC(%a6) 2688 bra.b iea_op_exit2 2689 2690iea_op_exc_unfl: 2691 mov.w &0xe003,2+FP_SRC(%a6) 2692 2693iea_op_exit2: 2694 mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC" 2695 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame 2696 2697 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 2698 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2699 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2700 2701 frestore FP_SRC(%a6) # restore exceptional state 2702 2703 unlk %a6 # unravel the frame 2704 2705 btst &0x7,(%sp) # is trace on? 2706 bne.b iea_op_trace # yes 2707 2708 bra.l _fpsp_done # exit to os 2709 2710# 2711# The opclass two instruction that took an "Unimplemented Effective Address" 2712# exception was being traced. Make the "current" PC the FPIAR and put it in 2713# the trace stack frame then jump to _real_trace(). 2714# 2715# UNIMP EA FRAME TRACE FRAME 2716# ***************** ***************** 2717# * 0x0 * 0x0f0 * * Current * 2718# ***************** * PC * 2719# * Current * ***************** 2720# * PC * * 0x2 * 0x024 * 2721# ***************** ***************** 2722# * SR * * Next * 2723# ***************** * PC * 2724# ***************** 2725# * SR * 2726# ***************** 2727iea_op_trace: 2728 mov.l (%sp),-(%sp) # shift stack frame "down" 2729 mov.w 0x8(%sp),0x4(%sp) 2730 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024 2731 fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR 2732 2733 bra.l _real_trace 2734 2735######################################################################### 2736iea_fmovm: 2737 btst &14,%d0 # ctrl or data reg 2738 beq.w iea_fmovm_ctrl 2739 2740iea_fmovm_data: 2741 2742 btst &0x5,EXC_SR(%a6) # user or supervisor mode 2743 bne.b iea_fmovm_data_s 2744 2745iea_fmovm_data_u: 2746 mov.l %usp,%a0 2747 mov.l %a0,EXC_A7(%a6) # store current a7 2748 bsr.l fmovm_dynamic # do dynamic fmovm 2749 mov.l EXC_A7(%a6),%a0 # load possibly new a7 2750 mov.l %a0,%usp # update usp 2751 bra.w iea_fmovm_exit 2752 2753iea_fmovm_data_s: 2754 clr.b SPCOND_FLG(%a6) 2755 lea 0x2+EXC_VOFF(%a6),%a0 2756 mov.l %a0,EXC_A7(%a6) 2757 bsr.l fmovm_dynamic # do dynamic fmovm 2758 2759 cmpi.b SPCOND_FLG(%a6),&mda7_flg 2760 beq.w iea_fmovm_data_predec 2761 cmpi.b SPCOND_FLG(%a6),&mia7_flg 2762 bne.w iea_fmovm_exit 2763 2764# right now, d0 = the size. 2765# the data has been fetched from the supervisor stack, but we have not 2766# incremented the stack pointer by the appropriate number of bytes. 2767# do it here. 2768iea_fmovm_data_postinc: 2769 btst &0x7,EXC_SR(%a6) 2770 bne.b iea_fmovm_data_pi_trace 2771 2772 mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0) 2773 mov.l EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0) 2774 mov.w &0x00f0,(EXC_VOFF,%a6,%d0) 2775 2776 lea (EXC_SR,%a6,%d0),%a0 2777 mov.l %a0,EXC_SR(%a6) 2778 2779 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 2780 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2781 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2782 2783 unlk %a6 2784 mov.l (%sp)+,%sp 2785 bra.l _fpsp_done 2786 2787iea_fmovm_data_pi_trace: 2788 mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0) 2789 mov.l EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0) 2790 mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0) 2791 mov.l EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0) 2792 2793 lea (EXC_SR-0x4,%a6,%d0),%a0 2794 mov.l %a0,EXC_SR(%a6) 2795 2796 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 2797 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2798 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2799 2800 unlk %a6 2801 mov.l (%sp)+,%sp 2802 bra.l _real_trace 2803 2804# right now, d1 = size and d0 = the strg. 2805iea_fmovm_data_predec: 2806 mov.b %d1,EXC_VOFF(%a6) # store strg 2807 mov.b %d0,0x1+EXC_VOFF(%a6) # store size 2808 2809 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 2810 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2811 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2812 2813 mov.l (%a6),-(%sp) # make a copy of a6 2814 mov.l %d0,-(%sp) # save d0 2815 mov.l %d1,-(%sp) # save d1 2816 mov.l EXC_EXTWPTR(%a6),-(%sp) # make a copy of Next PC 2817 2818 clr.l %d0 2819 mov.b 0x1+EXC_VOFF(%a6),%d0 # fetch size 2820 neg.l %d0 # get negative of size 2821 2822 btst &0x7,EXC_SR(%a6) # is trace enabled? 2823 beq.b iea_fmovm_data_p2 2824 2825 mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0) 2826 mov.l EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0) 2827 mov.l (%sp)+,(EXC_PC-0x4,%a6,%d0) 2828 mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0) 2829 2830 pea (%a6,%d0) # create final sp 2831 bra.b iea_fmovm_data_p3 2832 2833iea_fmovm_data_p2: 2834 mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0) 2835 mov.l (%sp)+,(EXC_PC,%a6,%d0) 2836 mov.w &0x00f0,(EXC_VOFF,%a6,%d0) 2837 2838 pea (0x4,%a6,%d0) # create final sp 2839 2840iea_fmovm_data_p3: 2841 clr.l %d1 2842 mov.b EXC_VOFF(%a6),%d1 # fetch strg 2843 2844 tst.b %d1 2845 bpl.b fm_1 2846 fmovm.x &0x80,(0x4+0x8,%a6,%d0) 2847 addi.l &0xc,%d0 2848fm_1: 2849 lsl.b &0x1,%d1 2850 bpl.b fm_2 2851 fmovm.x &0x40,(0x4+0x8,%a6,%d0) 2852 addi.l &0xc,%d0 2853fm_2: 2854 lsl.b &0x1,%d1 2855 bpl.b fm_3 2856 fmovm.x &0x20,(0x4+0x8,%a6,%d0) 2857 addi.l &0xc,%d0 2858fm_3: 2859 lsl.b &0x1,%d1 2860 bpl.b fm_4 2861 fmovm.x &0x10,(0x4+0x8,%a6,%d0) 2862 addi.l &0xc,%d0 2863fm_4: 2864 lsl.b &0x1,%d1 2865 bpl.b fm_5 2866 fmovm.x &0x08,(0x4+0x8,%a6,%d0) 2867 addi.l &0xc,%d0 2868fm_5: 2869 lsl.b &0x1,%d1 2870 bpl.b fm_6 2871 fmovm.x &0x04,(0x4+0x8,%a6,%d0) 2872 addi.l &0xc,%d0 2873fm_6: 2874 lsl.b &0x1,%d1 2875 bpl.b fm_7 2876 fmovm.x &0x02,(0x4+0x8,%a6,%d0) 2877 addi.l &0xc,%d0 2878fm_7: 2879 lsl.b &0x1,%d1 2880 bpl.b fm_end 2881 fmovm.x &0x01,(0x4+0x8,%a6,%d0) 2882fm_end: 2883 mov.l 0x4(%sp),%d1 2884 mov.l 0x8(%sp),%d0 2885 mov.l 0xc(%sp),%a6 2886 mov.l (%sp)+,%sp 2887 2888 btst &0x7,(%sp) # is trace enabled? 2889 beq.l _fpsp_done 2890 bra.l _real_trace 2891 2892######################################################################### 2893iea_fmovm_ctrl: 2894 2895 bsr.l fmovm_ctrl # load ctrl regs 2896 2897iea_fmovm_exit: 2898 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 2899 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 2900 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2901 2902 btst &0x7,EXC_SR(%a6) # is trace on? 2903 bne.b iea_fmovm_trace # yes 2904 2905 mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC 2906 2907 unlk %a6 # unravel the frame 2908 2909 bra.l _fpsp_done # exit to os 2910 2911# 2912# The control reg instruction that took an "Unimplemented Effective Address" 2913# exception was being traced. The "Current PC" for the trace frame is the 2914# PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR. 2915# After fixing the stack frame, jump to _real_trace(). 2916# 2917# UNIMP EA FRAME TRACE FRAME 2918# ***************** ***************** 2919# * 0x0 * 0x0f0 * * Current * 2920# ***************** * PC * 2921# * Current * ***************** 2922# * PC * * 0x2 * 0x024 * 2923# ***************** ***************** 2924# * SR * * Next * 2925# ***************** * PC * 2926# ***************** 2927# * SR * 2928# ***************** 2929# this ain't a pretty solution, but it works: 2930# -restore a6 (not with unlk) 2931# -shift stack frame down over where old a6 used to be 2932# -add LOCAL_SIZE to stack pointer 2933iea_fmovm_trace: 2934 mov.l (%a6),%a6 # restore frame pointer 2935 mov.w EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp) 2936 mov.l EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp) 2937 mov.l EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp) 2938 mov.w &0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024 2939 add.l &LOCAL_SIZE,%sp # clear stack frame 2940 2941 bra.l _real_trace 2942 2943######################################################################### 2944# The FPU is disabled and so we should really have taken the "Line 2945# F Emulator" exception. So, here we create an 8-word stack frame 2946# from our 4-word stack frame. This means we must calculate the length 2947# the faulting instruction to get the "next PC". This is trivial for 2948# immediate operands but requires some extra work for fmovm dynamic 2949# which can use most addressing modes. 2950iea_disabled: 2951 mov.l (%sp)+,%d0 # restore d0 2952 2953 link %a6,&-LOCAL_SIZE # init stack frame 2954 2955 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 2956 2957# PC of instruction that took the exception is the PC in the frame 2958 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6) 2959 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 2960 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 2961 bsr.l _imem_read_long # fetch the instruction words 2962 mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD 2963 2964 tst.w %d0 # is instr fmovm? 2965 bmi.b iea_dis_fmovm # yes 2966# instruction is using an extended precision immediate operand. Therefore, 2967# the total instruction length is 16 bytes. 2968iea_dis_immed: 2969 mov.l &0x10,%d0 # 16 bytes of instruction 2970 bra.b iea_dis_cont 2971iea_dis_fmovm: 2972 btst &0xe,%d0 # is instr fmovm ctrl 2973 bne.b iea_dis_fmovm_data # no 2974# the instruction is a fmovm.l with 2 or 3 registers. 2975 bfextu %d0{&19:&3},%d1 2976 mov.l &0xc,%d0 2977 cmpi.b %d1,&0x7 # move all regs? 2978 bne.b iea_dis_cont 2979 addq.l &0x4,%d0 2980 bra.b iea_dis_cont 2981# the instruction is an fmovm.x dynamic which can use many addressing 2982# modes and thus can have several different total instruction lengths. 2983# call fmovm_calc_ea which will go through the ea calc process and, 2984# as a by-product, will tell us how long the instruction is. 2985iea_dis_fmovm_data: 2986 clr.l %d0 2987 bsr.l fmovm_calc_ea 2988 mov.l EXC_EXTWPTR(%a6),%d0 2989 sub.l EXC_PC(%a6),%d0 2990iea_dis_cont: 2991 mov.w %d0,EXC_VOFF(%a6) # store stack shift value 2992 2993 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 2994 2995 unlk %a6 2996 2997# here, we actually create the 8-word frame from the 4-word frame, 2998# with the "next PC" as additional info. 2999# the <ea> field is let as undefined. 3000 subq.l &0x8,%sp # make room for new stack
3001 mov.l %d0,-(%sp) # save d0 3002 mov.w 0xc(%sp),0x4(%sp) # move SR 3003 mov.l 0xe(%sp),0x6(%sp) # move Current PC 3004 clr.l %d0 3005 mov.w 0x12(%sp),%d0 3006 mov.l 0x6(%sp),0x10(%sp) # move Current PC 3007 add.l %d0,0x6(%sp) # make Next PC 3008 mov.w &0x402c,0xa(%sp) # insert offset,frame format 3009 mov.l (%sp)+,%d0 # restore d0 3010 3011 bra.l _real_fpu_disabled 3012 3013########## 3014 3015iea_iacc: 3016 movc %pcr,%d0 3017 btst &0x1,%d0 3018 bne.b iea_iacc_cont 3019 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 3020 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack 3021iea_iacc_cont: 3022 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3023 3024 unlk %a6 3025 3026 subq.w &0x8,%sp # make stack frame bigger 3027 mov.l 0x8(%sp),(%sp) # store SR,hi(PC) 3028 mov.w 0xc(%sp),0x4(%sp) # store lo(PC) 3029 mov.w &0x4008,0x6(%sp) # store voff 3030 mov.l 0x2(%sp),0x8(%sp) # store ea 3031 mov.l &0x09428001,0xc(%sp) # store fslw 3032 3033iea_acc_done: 3034 btst &0x5,(%sp) # user or supervisor mode? 3035 beq.b iea_acc_done2 # user 3036 bset &0x2,0xd(%sp) # set supervisor TM bit 3037 3038iea_acc_done2: 3039 bra.l _real_access 3040 3041iea_dacc: 3042 lea -LOCAL_SIZE(%a6),%sp 3043 3044 movc %pcr,%d1 3045 btst &0x1,%d1 3046 bne.b iea_dacc_cont 3047 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack 3048 fmovm.l LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs 3049iea_dacc_cont: 3050 mov.l (%a6),%a6 3051 3052 mov.l 0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp) 3053 mov.w 0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp) 3054 mov.w &0x4008,-0x8+0xa+LOCAL_SIZE(%sp) 3055 mov.l %a0,-0x8+0xc+LOCAL_SIZE(%sp) 3056 mov.w %d0,-0x8+0x10+LOCAL_SIZE(%sp) 3057 mov.w &0x0001,-0x8+0x12+LOCAL_SIZE(%sp) 3058 3059 movm.l LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1 3060 add.w &LOCAL_SIZE-0x4,%sp 3061 3062 bra.b iea_acc_done 3063 3064######################################################################### 3065# XDEF **************************************************************** # 3066# _fpsp_operr(): 060FPSP entry point for FP Operr exception. # 3067# # 3068# This handler should be the first code executed upon taking the # 3069# FP Operand Error exception in an operating system. # 3070# # 3071# XREF **************************************************************** # 3072# _imem_read_long() - read instruction longword # 3073# fix_skewed_ops() - adjust src operand in fsave frame # 3074# _real_operr() - "callout" to operating system operr handler # 3075# _dmem_write_{byte,word,long}() - store data to mem (opclass 3) # 3076# store_dreg_{b,w,l}() - store data to data regfile (opclass 3) # 3077# facc_out_{b,w,l}() - store to memory took access error (opcl 3) # 3078# # 3079# INPUT *************************************************************** # 3080# - The system stack contains the FP Operr exception frame # 3081# - The fsave frame contains the source operand # 3082# # 3083# OUTPUT ************************************************************** # 3084# No access error: # 3085# - The system stack is unchanged # 3086# - The fsave frame contains the adjusted src op for opclass 0,2 # 3087# # 3088# ALGORITHM *********************************************************** # 3089# In a system where the FP Operr exception is enabled, the goal # 3090# is to get to the handler specified at _real_operr(). But, on the 060, # 3091# for opclass zero and two instruction taking this exception, the # 3092# input operand in the fsave frame may be incorrect for some cases # 3093# and needs to be corrected. This handler calls fix_skewed_ops() to # 3094# do just this and then exits through _real_operr(). # 3095# For opclass 3 instructions, the 060 doesn't store the default # 3096# operr result out to memory or data register file as it should. # 3097# This code must emulate the move out before finally exiting through # 3098# _real_inex(). The move out, if to memory, is performed using # 3099# _mem_write() "callout" routines that may return a failing result. # 3100# In this special case, the handler must exit through facc_out() # 3101# which creates an access error stack frame from the current operr # 3102# stack frame. # 3103# # 3104######################################################################### 3105 3106 global _fpsp_operr 3107_fpsp_operr: 3108 3109 link.w %a6,&-LOCAL_SIZE # init stack frame 3110 3111 fsave FP_SRC(%a6) # grab the "busy" frame 3112 3113 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 3114 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 3115 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 3116 3117# the FPIAR holds the "current PC" of the faulting instruction 3118 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 3119 3120 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 3121 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 3122 bsr.l _imem_read_long # fetch the instruction words 3123 mov.l %d0,EXC_OPWORD(%a6) 3124 3125############################################################################## 3126 3127 btst &13,%d0 # is instr an fmove out? 3128 bne.b foperr_out # fmove out 3129 3130 3131# here, we simply see if the operand in the fsave frame needs to be "unskewed". 3132# this would be the case for opclass two operations with a source infinity or 3133# denorm operand in the sgl or dbl format. NANs also become skewed, but can't 3134# cause an operr so we don't need to check for them here. 3135 lea FP_SRC(%a6),%a0 # pass: ptr to src op 3136 bsr.l fix_skewed_ops # fix src op 3137 3138foperr_exit: 3139 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 3140 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 3141 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3142 3143 frestore FP_SRC(%a6) 3144 3145 unlk %a6 3146 bra.l _real_operr 3147 3148######################################################################## 3149 3150# 3151# the hardware does not save the default result to memory on enabled 3152# operand error exceptions. we do this here before passing control to 3153# the user operand error handler. 3154# 3155# byte, word, and long destination format operations can pass 3156# through here. we simply need to test the sign of the src 3157# operand and save the appropriate minimum or maximum integer value 3158# to the effective address as pointed to by the stacked effective address. 3159# 3160# although packed opclass three operations can take operand error 3161# exceptions, they won't pass through here since they are caught 3162# first by the unsupported data format exception handler. that handler 3163# sends them directly to _real_operr() if necessary. 3164# 3165foperr_out: 3166 3167 mov.w FP_SRC_EX(%a6),%d1 # fetch exponent 3168 andi.w &0x7fff,%d1 3169 cmpi.w %d1,&0x7fff 3170 bne.b foperr_out_not_qnan 3171# the operand is either an infinity or a QNAN. 3172 tst.l FP_SRC_LO(%a6) 3173 bne.b foperr_out_qnan 3174 mov.l FP_SRC_HI(%a6),%d1 3175 andi.l &0x7fffffff,%d1 3176 beq.b foperr_out_not_qnan 3177foperr_out_qnan: 3178 mov.l FP_SRC_HI(%a6),L_SCR1(%a6) 3179 bra.b foperr_out_jmp 3180 3181foperr_out_not_qnan: 3182 mov.l &0x7fffffff,%d1 3183 tst.b FP_SRC_EX(%a6) 3184 bpl.b foperr_out_not_qnan2 3185 addq.l &0x1,%d1 3186foperr_out_not_qnan2: 3187 mov.l %d1,L_SCR1(%a6) 3188 3189foperr_out_jmp: 3190 bfextu %d0{&19:&3},%d0 # extract dst format field 3191 mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg 3192 mov.w (tbl_operr.b,%pc,%d0.w*2),%a0 3193 jmp (tbl_operr.b,%pc,%a0) 3194 3195tbl_operr: 3196 short foperr_out_l - tbl_operr # long word integer 3197 short tbl_operr - tbl_operr # sgl prec shouldn't happen 3198 short tbl_operr - tbl_operr # ext prec shouldn't happen 3199 short foperr_exit - tbl_operr # packed won't enter here 3200 short foperr_out_w - tbl_operr # word integer 3201 short tbl_operr - tbl_operr # dbl prec shouldn't happen 3202 short foperr_out_b - tbl_operr # byte integer 3203 short tbl_operr - tbl_operr # packed won't enter here 3204 3205foperr_out_b: 3206 mov.b L_SCR1(%a6),%d0 # load positive default result 3207 cmpi.b %d1,&0x7 # is <ea> mode a data reg? 3208 ble.b foperr_out_b_save_dn # yes 3209 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result 3210 bsr.l _dmem_write_byte # write the default result 3211 3212 tst.l %d1 # did dstore fail? 3213 bne.l facc_out_b # yes 3214 3215 bra.w foperr_exit 3216foperr_out_b_save_dn: 3217 andi.w &0x0007,%d1 3218 bsr.l store_dreg_b # store result to regfile 3219 bra.w foperr_exit 3220 3221foperr_out_w: 3222 mov.w L_SCR1(%a6),%d0 # load positive default result 3223 cmpi.b %d1,&0x7 # is <ea> mode a data reg? 3224 ble.b foperr_out_w_save_dn # yes 3225 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result 3226 bsr.l _dmem_write_word # write the default result 3227 3228 tst.l %d1 # did dstore fail? 3229 bne.l facc_out_w # yes 3230 3231 bra.w foperr_exit 3232foperr_out_w_save_dn: 3233 andi.w &0x0007,%d1 3234 bsr.l store_dreg_w # store result to regfile 3235 bra.w foperr_exit 3236 3237foperr_out_l: 3238 mov.l L_SCR1(%a6),%d0 # load positive default result 3239 cmpi.b %d1,&0x7 # is <ea> mode a data reg? 3240 ble.b foperr_out_l_save_dn # yes 3241 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result 3242 bsr.l _dmem_write_long # write the default result 3243 3244 tst.l %d1 # did dstore fail? 3245 bne.l facc_out_l # yes 3246 3247 bra.w foperr_exit 3248foperr_out_l_save_dn: 3249 andi.w &0x0007,%d1 3250 bsr.l store_dreg_l # store result to regfile 3251 bra.w foperr_exit 3252 3253######################################################################### 3254# XDEF **************************************************************** # 3255# _fpsp_snan(): 060FPSP entry point for FP SNAN exception. # 3256# # 3257# This handler should be the first code executed upon taking the # 3258# FP Signalling NAN exception in an operating system. # 3259# # 3260# XREF **************************************************************** # 3261# _imem_read_long() - read instruction longword # 3262# fix_skewed_ops() - adjust src operand in fsave frame # 3263# _real_snan() - "callout" to operating system SNAN handler # 3264# _dmem_write_{byte,word,long}() - store data to mem (opclass 3) # 3265# store_dreg_{b,w,l}() - store data to data regfile (opclass 3) # 3266# facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3) # 3267# _calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea> # 3268# # 3269# INPUT *************************************************************** # 3270# - The system stack contains the FP SNAN exception frame # 3271# - The fsave frame contains the source operand # 3272# # 3273# OUTPUT ************************************************************** # 3274# No access error: # 3275# - The system stack is unchanged # 3276# - The fsave frame contains the adjusted src op for opclass 0,2 # 3277# # 3278# ALGORITHM *********************************************************** # 3279# In a system where the FP SNAN exception is enabled, the goal # 3280# is to get to the handler specified at _real_snan(). But, on the 060, # 3281# for opclass zero and two instructions taking this exception, the # 3282# input operand in the fsave frame may be incorrect for some cases # 3283# and needs to be corrected. This handler calls fix_skewed_ops() to # 3284# do just this and then exits through _real_snan(). # 3285# For opclass 3 instructions, the 060 doesn't store the default # 3286# SNAN result out to memory or data register file as it should. # 3287# This code must emulate the move out before finally exiting through # 3288# _real_snan(). The move out, if to memory, is performed using # 3289# _mem_write() "callout" routines that may return a failing result. # 3290# In this special case, the handler must exit through facc_out() # 3291# which creates an access error stack frame from the current SNAN # 3292# stack frame. # 3293# For the case of an extended precision opclass 3 instruction, # 3294# if the effective addressing mode was -() or ()+, then the address # 3295# register must get updated by calling _calc_ea_fout(). If the <ea> # 3296# was -(a7) from supervisor mode, then the exception frame currently # 3297# on the system stack must be carefully moved "down" to make room # 3298# for the operand being moved. # 3299# # 3300######################################################################### 3301 3302 global _fpsp_snan 3303_fpsp_snan: 3304 3305 link.w %a6,&-LOCAL_SIZE # init stack frame 3306 3307 fsave FP_SRC(%a6) # grab the "busy" frame 3308 3309 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 3310 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 3311 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 3312 3313# the FPIAR holds the "current PC" of the faulting instruction 3314 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 3315 3316 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 3317 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 3318 bsr.l _imem_read_long # fetch the instruction words 3319 mov.l %d0,EXC_OPWORD(%a6) 3320 3321############################################################################## 3322 3323 btst &13,%d0 # is instr an fmove out? 3324 bne.w fsnan_out # fmove out 3325 3326 3327# here, we simply see if the operand in the fsave frame needs to be "unskewed". 3328# this would be the case for opclass two operations with a source infinity or 3329# denorm operand in the sgl or dbl format. NANs also become skewed and must be 3330# fixed here. 3331 lea FP_SRC(%a6),%a0 # pass: ptr to src op 3332 bsr.l fix_skewed_ops # fix src op 3333 3334fsnan_exit: 3335 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 3336 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 3337 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3338 3339 frestore FP_SRC(%a6) 3340 3341 unlk %a6 3342 bra.l _real_snan 3343 3344######################################################################## 3345 3346# 3347# the hardware does not save the default result to memory on enabled 3348# snan exceptions. we do this here before passing control to 3349# the user snan handler. 3350# 3351# byte, word, long, and packed destination format operations can pass 3352# through here. since packed format operations already were handled by 3353# fpsp_unsupp(), then we need to do nothing else for them here. 3354# for byte, word, and long, we simply need to test the sign of the src 3355# operand and save the appropriate minimum or maximum integer value 3356# to the effective address as pointed to by the stacked effective address. 3357# 3358fsnan_out: 3359 3360 bfextu %d0{&19:&3},%d0 # extract dst format field 3361 mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg 3362 mov.w (tbl_snan.b,%pc,%d0.w*2),%a0 3363 jmp (tbl_snan.b,%pc,%a0) 3364 3365tbl_snan: 3366 short fsnan_out_l - tbl_snan # long word integer 3367 short fsnan_out_s - tbl_snan # sgl prec shouldn't happen 3368 short fsnan_out_x - tbl_snan # ext prec shouldn't happen 3369 short tbl_snan - tbl_snan # packed needs no help 3370 short fsnan_out_w - tbl_snan # word integer 3371 short fsnan_out_d - tbl_snan # dbl prec shouldn't happen 3372 short fsnan_out_b - tbl_snan # byte integer 3373 short tbl_snan - tbl_snan # packed needs no help 3374 3375fsnan_out_b: 3376 mov.b FP_SRC_HI(%a6),%d0 # load upper byte of SNAN 3377 bset &6,%d0 # set SNAN bit 3378 cmpi.b %d1,&0x7 # is <ea> mode a data reg? 3379 ble.b fsnan_out_b_dn # yes 3380 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result 3381 bsr.l _dmem_write_byte # write the default result 3382 3383 tst.l %d1 # did dstore fail? 3384 bne.l facc_out_b # yes 3385 3386 bra.w fsnan_exit 3387fsnan_out_b_dn: 3388 andi.w &0x0007,%d1 3389 bsr.l store_dreg_b # store result to regfile 3390 bra.w fsnan_exit 3391 3392fsnan_out_w: 3393 mov.w FP_SRC_HI(%a6),%d0 # load upper word of SNAN 3394 bset &14,%d0 # set SNAN bit 3395 cmpi.b %d1,&0x7 # is <ea> mode a data reg? 3396 ble.b fsnan_out_w_dn # yes 3397 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result 3398 bsr.l _dmem_write_word # write the default result 3399 3400 tst.l %d1 # did dstore fail? 3401 bne.l facc_out_w # yes 3402 3403 bra.w fsnan_exit 3404fsnan_out_w_dn: 3405 andi.w &0x0007,%d1 3406 bsr.l store_dreg_w # store result to regfile 3407 bra.w fsnan_exit 3408 3409fsnan_out_l: 3410 mov.l FP_SRC_HI(%a6),%d0 # load upper longword of SNAN 3411 bset &30,%d0 # set SNAN bit 3412 cmpi.b %d1,&0x7 # is <ea> mode a data reg? 3413 ble.b fsnan_out_l_dn # yes 3414 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result 3415 bsr.l _dmem_write_long # write the default result 3416 3417 tst.l %d1 # did dstore fail? 3418 bne.l facc_out_l # yes 3419 3420 bra.w fsnan_exit 3421fsnan_out_l_dn: 3422 andi.w &0x0007,%d1 3423 bsr.l store_dreg_l # store result to regfile 3424 bra.w fsnan_exit 3425 3426fsnan_out_s: 3427 cmpi.b %d1,&0x7 # is <ea> mode a data reg? 3428 ble.b fsnan_out_d_dn # yes 3429 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign 3430 andi.l &0x80000000,%d0 # keep sign 3431 ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit 3432 mov.l FP_SRC_HI(%a6),%d1 # load mantissa 3433 lsr.l &0x8,%d1 # shift mantissa for sgl 3434 or.l %d1,%d0 # create sgl SNAN 3435 mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result 3436 bsr.l _dmem_write_long # write the default result 3437 3438 tst.l %d1 # did dstore fail? 3439 bne.l facc_out_l # yes 3440 3441 bra.w fsnan_exit 3442fsnan_out_d_dn: 3443 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign 3444 andi.l &0x80000000,%d0 # keep sign 3445 ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit 3446 mov.l %d1,-(%sp) 3447 mov.l FP_SRC_HI(%a6),%d1 # load mantissa 3448 lsr.l &0x8,%d1 # shift mantissa for sgl 3449 or.l %d1,%d0 # create sgl SNAN 3450 mov.l (%sp)+,%d1 3451 andi.w &0x0007,%d1 3452 bsr.l store_dreg_l # store result to regfile 3453 bra.w fsnan_exit 3454 3455fsnan_out_d: 3456 mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign 3457 andi.l &0x80000000,%d0 # keep sign 3458 ori.l &0x7ff80000,%d0 # insert new exponent,SNAN bit 3459 mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa 3460 mov.l %d0,FP_SCR0_EX(%a6) # store to temp space 3461 mov.l &11,%d0 # load shift amt 3462 lsr.l %d0,%d1 3463 or.l %d1,FP_SCR0_EX(%a6) # create dbl hi 3464 mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa 3465 andi.l &0x000007ff,%d1 3466 ror.l %d0,%d1 3467 mov.l %d1,FP_SCR0_HI(%a6) # store to temp space 3468 mov.l FP_SRC_LO(%a6),%d1 # load lo mantissa 3469 lsr.l %d0,%d1 3470 or.l %d1,FP_SCR0_HI(%a6) # create dbl lo 3471 lea FP_SCR0(%a6),%a0 # pass: ptr to operand 3472 mov.l EXC_EA(%a6),%a1 # pass: dst addr 3473 movq.l &0x8,%d0 # pass: size of 8 bytes 3474 bsr.l _dmem_write # write the default result 3475 3476 tst.l %d1 # did dstore fail? 3477 bne.l facc_out_d # yes 3478 3479 bra.w fsnan_exit 3480 3481# for extended precision, if the addressing mode is pre-decrement or 3482# post-increment, then the address register did not get updated. 3483# in addition, for pre-decrement, the stacked <ea> is incorrect. 3484fsnan_out_x: 3485 clr.b SPCOND_FLG(%a6) # clear special case flag 3486 3487 mov.w FP_SRC_EX(%a6),FP_SCR0_EX(%a6) 3488 clr.w 2+FP_SCR0(%a6) 3489 mov.l FP_SRC_HI(%a6),%d0 3490 bset &30,%d0 3491 mov.l %d0,FP_SCR0_HI(%a6) 3492 mov.l FP_SRC_LO(%a6),FP_SCR0_LO(%a6) 3493 3494 btst &0x5,EXC_SR(%a6) # supervisor mode exception? 3495 bne.b fsnan_out_x_s # yes 3496 3497 mov.l %usp,%a0 # fetch user stack pointer 3498 mov.l %a0,EXC_A7(%a6) # save on stack for calc_ea() 3499 mov.l (%a6),EXC_A6(%a6) 3500 3501 bsr.l _calc_ea_fout # find the correct ea,update An 3502 mov.l %a0,%a1 3503 mov.l %a0,EXC_EA(%a6) # stack correct <ea> 3504 3505 mov.l EXC_A7(%a6),%a0 3506 mov.l %a0,%usp # restore user stack pointer 3507 mov.l EXC_A6(%a6),(%a6) 3508 3509fsnan_out_x_save: 3510 lea FP_SCR0(%a6),%a0 # pass: ptr to operand 3511 movq.l &0xc,%d0 # pass: size of extended 3512 bsr.l _dmem_write # write the default result 3513 3514 tst.l %d1 # did dstore fail? 3515 bne.l facc_out_x # yes 3516 3517 bra.w fsnan_exit 3518 3519fsnan_out_x_s: 3520 mov.l (%a6),EXC_A6(%a6) 3521 3522 bsr.l _calc_ea_fout # find the correct ea,update An 3523 mov.l %a0,%a1 3524 mov.l %a0,EXC_EA(%a6) # stack correct <ea> 3525 3526 mov.l EXC_A6(%a6),(%a6) 3527 3528 cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)? 3529 bne.b fsnan_out_x_save # no 3530 3531# the operation was "fmove.x SNAN,-(a7)" from supervisor mode. 3532 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 3533 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 3534 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3535 3536 frestore FP_SRC(%a6) 3537 3538 mov.l EXC_A6(%a6),%a6 # restore frame pointer 3539 3540 mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) 3541 mov.l LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp) 3542 mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp) 3543 3544 mov.l LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp) 3545 mov.l LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp) 3546 mov.l LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp) 3547 3548 add.l &LOCAL_SIZE-0x8,%sp 3549 3550 bra.l _real_snan 3551 3552######################################################################### 3553# XDEF **************************************************************** # 3554# _fpsp_inex(): 060FPSP entry point for FP Inexact exception. # 3555# # 3556# This handler should be the first code executed upon taking the # 3557# FP Inexact exception in an operating system. # 3558# # 3559# XREF **************************************************************** # 3560# _imem_read_long() - read instruction longword # 3561# fix_skewed_ops() - adjust src operand in fsave frame # 3562# set_tag_x() - determine optype of src/dst operands # 3563# store_fpreg() - store opclass 0 or 2 result to FP regfile # 3564# unnorm_fix() - change UNNORM operands to NORM or ZERO # 3565# load_fpn2() - load dst operand from FP regfile # 3566# smovcr() - emulate an "fmovcr" instruction # 3567# fout() - emulate an opclass 3 instruction # 3568# tbl_unsupp - add of table of emulation routines for opclass 0,2 # 3569# _real_inex() - "callout" to operating system inexact handler # 3570# # 3571# INPUT *************************************************************** # 3572# - The system stack contains the FP Inexact exception frame # 3573# - The fsave frame contains the source operand # 3574# # 3575# OUTPUT ************************************************************** # 3576# - The system stack is unchanged # 3577# - The fsave frame contains the adjusted src op for opclass 0,2 # 3578# # 3579# ALGORITHM *********************************************************** # 3580# In a system where the FP Inexact exception is enabled, the goal # 3581# is to get to the handler specified at _real_inex(). But, on the 060, # 3582# for opclass zero and two instruction taking this exception, the # 3583# hardware doesn't store the correct result to the destination FP # 3584# register as did the '040 and '881/2. This handler must emulate the # 3585# instruction in order to get this value and then store it to the # 3586# correct register before calling _real_inex(). # 3587# For opclass 3 instructions, the 060 doesn't store the default # 3588# inexact result out to memory or data register file as it should. # 3589# This code must emulate the move out by calling fout() before finally # 3590# exiting through _real_inex(). # 3591# # 3592######################################################################### 3593 3594 global _fpsp_inex 3595_fpsp_inex: 3596 3597 link.w %a6,&-LOCAL_SIZE # init stack frame 3598 3599 fsave FP_SRC(%a6) # grab the "busy" frame 3600 3601 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 3602 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 3603 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 3604 3605# the FPIAR holds the "current PC" of the faulting instruction 3606 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 3607 3608 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 3609 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 3610 bsr.l _imem_read_long # fetch the instruction words 3611 mov.l %d0,EXC_OPWORD(%a6) 3612 3613############################################################################## 3614 3615 btst &13,%d0 # is instr an fmove out? 3616 bne.w finex_out # fmove out 3617 3618 3619# the hardware, for "fabs" and "fneg" w/ a long source format, puts the 3620# longword integer directly into the upper longword of the mantissa along 3621# w/ an exponent value of 0x401e. we convert this to extended precision here. 3622 bfextu %d0{&19:&3},%d0 # fetch instr size 3623 bne.b finex_cont # instr size is not long 3624 cmpi.w FP_SRC_EX(%a6),&0x401e # is exponent 0x401e? 3625 bne.b finex_cont # no 3626 fmov.l &0x0,%fpcr 3627 fmov.l FP_SRC_HI(%a6),%fp0 # load integer src 3628 fmov.x %fp0,FP_SRC(%a6) # store integer as extended precision 3629 mov.w &0xe001,0x2+FP_SRC(%a6) 3630 3631finex_cont: 3632 lea FP_SRC(%a6),%a0 # pass: ptr to src op 3633 bsr.l fix_skewed_ops # fix src op 3634 3635# Here, we zero the ccode and exception byte field since we're going to 3636# emulate the whole instruction. Notice, though, that we don't kill the 3637# INEX1 bit. This is because a packed op has long since been converted 3638# to extended before arriving here. Therefore, we need to retain the 3639# INEX1 bit from when the operand was first converted. 3640 andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field 3641 3642 fmov.l &0x0,%fpcr # zero current control regs 3643 fmov.l &0x0,%fpsr 3644 3645 bfextu EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg 3646 cmpi.b %d1,&0x17 # is op an fmovecr? 3647 beq.w finex_fmovcr # yes 3648 3649 lea FP_SRC(%a6),%a0 # pass: ptr to src op 3650 bsr.l set_tag_x # tag the operand type 3651 mov.b %d0,STAG(%a6) # maybe NORM,DENORM 3652 3653# bits four and five of the fp extension word separate the monadic and dyadic 3654# operations that can pass through fpsp_inex(). remember that fcmp and ftst 3655# will never take this exception, but fsincos will. 3656 btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic? 3657 beq.b finex_extract # monadic 3658 3659 btst &0x4,1+EXC_CMDREG(%a6) # is operation an fsincos? 3660 bne.b finex_extract # yes 3661 3662 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg 3663 bsr.l load_fpn2 # load dst into FP_DST 3664 3665 lea FP_DST(%a6),%a0 # pass: ptr to dst op 3666 bsr.l set_tag_x # tag the operand type 3667 cmpi.b %d0,&UNNORM # is operand an UNNORM? 3668 bne.b finex_op2_done # no 3669 bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO 3670finex_op2_done: 3671 mov.b %d0,DTAG(%a6) # save dst optype tag 3672 3673finex_extract: 3674 clr.l %d0 3675 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode 3676 3677 mov.b 1+EXC_CMDREG(%a6),%d1 3678 andi.w &0x007f,%d1 # extract extension 3679 3680 lea FP_SRC(%a6),%a0 3681 lea FP_DST(%a6),%a1 3682 3683 mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr 3684 jsr (tbl_unsupp.l,%pc,%d1.l*1) 3685 3686# the operation has been emulated. the result is in fp0. 3687finex_save: 3688 bfextu EXC_CMDREG(%a6){&6:&3},%d0 3689 bsr.l store_fpreg 3690 3691finex_exit: 3692 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 3693 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 3694 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3695 3696 frestore FP_SRC(%a6) 3697 3698 unlk %a6 3699 bra.l _real_inex 3700 3701finex_fmovcr: 3702 clr.l %d0 3703 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode 3704 mov.b 1+EXC_CMDREG(%a6),%d1 3705 andi.l &0x0000007f,%d1 # pass rom offset 3706 bsr.l smovcr 3707 bra.b finex_save 3708 3709######################################################################## 3710 3711# 3712# the hardware does not save the default result to memory on enabled 3713# inexact exceptions. we do this here before passing control to 3714# the user inexact handler. 3715# 3716# byte, word, and long destination format operations can pass 3717# through here. so can double and single precision. 3718# although packed opclass three operations can take inexact 3719# exceptions, they won't pass through here since they are caught 3720# first by the unsupported data format exception handler. that handler 3721# sends them directly to _real_inex() if necessary. 3722# 3723finex_out: 3724 3725 mov.b &NORM,STAG(%a6) # src is a NORM 3726 3727 clr.l %d0 3728 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode 3729 3730 andi.l &0xffff00ff,USER_FPSR(%a6) # zero exception field 3731 3732 lea FP_SRC(%a6),%a0 # pass ptr to src operand 3733 3734 bsr.l fout # store the default result 3735 3736 bra.b finex_exit 3737 3738######################################################################### 3739# XDEF **************************************************************** # 3740# _fpsp_dz(): 060FPSP entry point for FP DZ exception. # 3741# # 3742# This handler should be the first code executed upon taking # 3743# the FP DZ exception in an operating system. # 3744# # 3745# XREF **************************************************************** # 3746# _imem_read_long() - read instruction longword from memory # 3747# fix_skewed_ops() - adjust fsave operand # 3748# _real_dz() - "callout" exit point from FP DZ handler # 3749# # 3750# INPUT *************************************************************** # 3751# - The system stack contains the FP DZ exception stack. # 3752# - The fsave frame contains the source operand. # 3753# # 3754# OUTPUT ************************************************************** # 3755# - The system stack contains the FP DZ exception stack. # 3756# - The fsave frame contains the adjusted source operand. # 3757# # 3758# ALGORITHM *********************************************************** # 3759# In a system where the DZ exception is enabled, the goal is to # 3760# get to the handler specified at _real_dz(). But, on the 060, when the # 3761# exception is taken, the input operand in the fsave state frame may # 3762# be incorrect for some cases and need to be adjusted. So, this package # 3763# adjusts the operand using fix_skewed_ops() and then branches to # 3764# _real_dz(). # 3765# # 3766######################################################################### 3767 3768 global _fpsp_dz 3769_fpsp_dz: 3770 3771 link.w %a6,&-LOCAL_SIZE # init stack frame 3772 3773 fsave FP_SRC(%a6) # grab the "busy" frame 3774 3775 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 3776 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 3777 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack 3778 3779# the FPIAR holds the "current PC" of the faulting instruction 3780 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 3781 3782 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 3783 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 3784 bsr.l _imem_read_long # fetch the instruction words 3785 mov.l %d0,EXC_OPWORD(%a6) 3786 3787############################################################################## 3788 3789 3790# here, we simply see if the operand in the fsave frame needs to be "unskewed". 3791# this would be the case for opclass two operations with a source zero 3792# in the sgl or dbl format. 3793 lea FP_SRC(%a6),%a0 # pass: ptr to src op 3794 bsr.l fix_skewed_ops # fix src op 3795 3796fdz_exit: 3797 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 3798 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 3799 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3800 3801 frestore FP_SRC(%a6) 3802 3803 unlk %a6 3804 bra.l _real_dz 3805 3806######################################################################### 3807# XDEF **************************************************************** # 3808# _fpsp_fline(): 060FPSP entry point for "Line F emulator" exc. # 3809# # 3810# This handler should be the first code executed upon taking the # 3811# "Line F Emulator" exception in an operating system. # 3812# # 3813# XREF **************************************************************** # 3814# _fpsp_unimp() - handle "FP Unimplemented" exceptions # 3815# _real_fpu_disabled() - handle "FPU disabled" exceptions # 3816# _real_fline() - handle "FLINE" exceptions # 3817# _imem_read_long() - read instruction longword # 3818# # 3819# INPUT *************************************************************** # 3820# - The system stack contains a "Line F Emulator" exception # 3821# stack frame. # 3822# # 3823# OUTPUT ************************************************************** # 3824# - The system stack is unchanged # 3825# # 3826# ALGORITHM *********************************************************** # 3827# When a "Line F Emulator" exception occurs, there are 3 possible # 3828# exception types, denoted by the exception stack frame format number: # 3829# (1) FPU unimplemented instruction (6 word stack frame) # 3830# (2) FPU disabled (8 word stack frame) # 3831# (3) Line F (4 word stack frame) # 3832# # 3833# This module determines which and forks the flow off to the # 3834# appropriate "callout" (for "disabled" and "Line F") or to the # 3835# correct emulation code (for "FPU unimplemented"). # 3836# This code also must check for "fmovecr" instructions w/ a # 3837# non-zero <ea> field. These may get flagged as "Line F" but should # 3838# really be flagged as "FPU Unimplemented". (This is a "feature" on # 3839# the '060. # 3840# # 3841######################################################################### 3842 3843 global _fpsp_fline 3844_fpsp_fline: 3845 3846# check to see if this exception is a "FP Unimplemented Instruction" 3847# exception. if so, branch directly to that handler's entry point. 3848 cmpi.w 0x6(%sp),&0x202c 3849 beq.l _fpsp_unimp 3850 3851# check to see if the FPU is disabled. if so, jump to the OS entry 3852# point for that condition. 3853 cmpi.w 0x6(%sp),&0x402c 3854 beq.l _real_fpu_disabled 3855 3856# the exception was an "F-Line Illegal" exception. we check to see 3857# if the F-Line instruction is an "fmovecr" w/ a non-zero <ea>. if 3858# so, convert the F-Line exception stack frame to an FP Unimplemented 3859# Instruction exception stack frame else branch to the OS entry 3860# point for the F-Line exception handler. 3861 link.w %a6,&-LOCAL_SIZE # init stack frame 3862 3863 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 3864 3865 mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6) 3866 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 3867 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 3868 bsr.l _imem_read_long # fetch instruction words 3869 3870 bfextu %d0{&0:&10},%d1 # is it an fmovecr? 3871 cmpi.w %d1,&0x03c8 3872 bne.b fline_fline # no 3873 3874 bfextu %d0{&16:&6},%d1 # is it an fmovecr? 3875 cmpi.b %d1,&0x17 3876 bne.b fline_fline # no 3877 3878# it's an fmovecr w/ a non-zero <ea> that has entered through 3879# the F-Line Illegal exception. 3880# so, we need to convert the F-Line exception stack frame into an 3881# FP Unimplemented Instruction stack frame and jump to that entry 3882# point. 3883# 3884# but, if the FPU is disabled, then we need to jump to the FPU disabled 3885# entry point. 3886 movc %pcr,%d0 3887 btst &0x1,%d0 3888 beq.b fline_fmovcr 3889 3890 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3891 3892 unlk %a6 3893 3894 sub.l &0x8,%sp # make room for "Next PC", <ea> 3895 mov.w 0x8(%sp),(%sp) 3896 mov.l 0xa(%sp),0x2(%sp) # move "Current PC" 3897 mov.w &0x402c,0x6(%sp) 3898 mov.l 0x2(%sp),0xc(%sp) 3899 addq.l &0x4,0x2(%sp) # set "Next PC" 3900 3901 bra.l _real_fpu_disabled 3902 3903fline_fmovcr: 3904 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3905 3906 unlk %a6 3907 3908 fmov.l 0x2(%sp),%fpiar # set current PC 3909 addq.l &0x4,0x2(%sp) # set Next PC 3910 3911 mov.l (%sp),-(%sp) 3912 mov.l 0x8(%sp),0x4(%sp) 3913 mov.b &0x20,0x6(%sp) 3914 3915 bra.l _fpsp_unimp 3916 3917fline_fline: 3918 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 3919 3920 unlk %a6 3921 3922 bra.l _real_fline 3923 3924######################################################################### 3925# XDEF **************************************************************** # 3926# _fpsp_unimp(): 060FPSP entry point for FP "Unimplemented # 3927# Instruction" exception. # 3928# # 3929# This handler should be the first code executed upon taking the # 3930# FP Unimplemented Instruction exception in an operating system. # 3931# # 3932# XREF **************************************************************** # 3933# _imem_read_{word,long}() - read instruction word/longword # 3934# load_fop() - load src/dst ops from memory and/or FP regfile # 3935# store_fpreg() - store opclass 0 or 2 result to FP regfile # 3936# tbl_trans - addr of table of emulation routines for trnscndls # 3937# _real_access() - "callout" for access error exception # 3938# _fpsp_done() - "callout" for exit; work all done # 3939# _real_trace() - "callout" for Trace enabled exception # 3940# smovcr() - emulate "fmovecr" instruction # 3941# funimp_skew() - adjust fsave src ops to "incorrect" value # 3942# _ftrapcc() - emulate an "ftrapcc" instruction # 3943# _fdbcc() - emulate an "fdbcc" instruction # 3944# _fscc() - emulate an "fscc" instruction # 3945# _real_trap() - "callout" for Trap exception # 3946# _real_bsun() - "callout" for enabled Bsun exception # 3947# # 3948# INPUT *************************************************************** # 3949# - The system stack contains the "Unimplemented Instr" stk frame # 3950# # 3951# OUTPUT ************************************************************** # 3952# If access error: # 3953# - The system stack is changed to an access error stack frame # 3954# If Trace exception enabled: # 3955# - The system stack is changed to a Trace exception stack frame # 3956# Else: (normal case) # 3957# - Correct result has been stored as appropriate # 3958# # 3959# ALGORITHM *********************************************************** # 3960# There are two main cases of instructions that may enter here to # 3961# be emulated: (1) the FPgen instructions, most of which were also # 3962# unimplemented on the 040, and (2) "ftrapcc", "fscc", and "fdbcc". # 3963# For the first set, this handler calls the routine load_fop() # 3964# to load the source and destination (for dyadic) operands to be used # 3965# for instruction emulation. The correct emulation routine is then # 3966# chosen by decoding the instruction type and indexing into an # 3967# emulation subroutine index table. After emulation returns, this # 3968# handler checks to see if an exception should occur as a result of the # 3969# FP instruction emulation. If so, then an FP exception of the correct # 3970# type is inserted into the FPU state frame using the "frestore" # 3971# instruction before exiting through _fpsp_done(). In either the # 3972# exceptional or non-exceptional cases, we must check to see if the # 3973# Trace exception is enabled. If so, then we must create a Trace # 3974# exception frame from the current exception frame and exit through # 3975# _real_trace(). # 3976# For "fdbcc", "ftrapcc", and "fscc", the emulation subroutines # 3977# _fdbcc(), _ftrapcc(), and _fscc() respectively are used. All three # 3978# may flag that a BSUN exception should be taken. If so, then the # 3979# current exception stack frame is converted into a BSUN exception # 3980# stack frame and an exit is made through _real_bsun(). If the # 3981# instruction was "ftrapcc" and a Trap exception should result, a Trap # 3982# exception stack frame is created from the current frame and an exit # 3983# is made through _real_trap(). If a Trace exception is pending, then # 3984# a Trace exception frame is created from the current frame and a jump # 3985# is made to _real_trace(). Finally, if none of these conditions exist, # 3986# then the handler exits though the callout _fpsp_done(). # 3987# # 3988# In any of the above scenarios, if a _mem_read() or _mem_write() # 3989# "callout" returns a failing value, then an access error stack frame # 3990# is created from the current stack frame and an exit is made through # 3991# _real_access(). # 3992# # 3993######################################################################### 3994 3995# 3996# FP UNIMPLEMENTED INSTRUCTION STACK FRAME: 3997# 3998# ***************** 3999# * * => <ea> of fp unimp instr. 4000# - EA -
4001# * * 4002# ***************** 4003# * 0x2 * 0x02c * => frame format and vector offset(vector #11) 4004# ***************** 4005# * * 4006# - Next PC - => PC of instr to execute after exc handling 4007# * * 4008# ***************** 4009# * SR * => SR at the time the exception was taken 4010# ***************** 4011# 4012# Note: the !NULL bit does not get set in the fsave frame when the 4013# machine encounters an fp unimp exception. Therefore, it must be set 4014# before leaving this handler. 4015# 4016 global _fpsp_unimp 4017_fpsp_unimp: 4018 4019 link.w %a6,&-LOCAL_SIZE # init stack frame 4020 4021 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 4022 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs 4023 fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 4024 4025 btst &0x5,EXC_SR(%a6) # user mode exception? 4026 bne.b funimp_s # no; supervisor mode 4027 4028# save the value of the user stack pointer onto the stack frame 4029funimp_u: 4030 mov.l %usp,%a0 # fetch user stack pointer 4031 mov.l %a0,EXC_A7(%a6) # store in stack frame 4032 bra.b funimp_cont 4033 4034# store the value of the supervisor stack pointer BEFORE the exc occurred. 4035# old_sp is address just above stacked effective address. 4036funimp_s: 4037 lea 4+EXC_EA(%a6),%a0 # load old a7' 4038 mov.l %a0,EXC_A7(%a6) # store a7' 4039 mov.l %a0,OLD_A7(%a6) # make a copy 4040 4041funimp_cont: 4042 4043# the FPIAR holds the "current PC" of the faulting instruction. 4044 mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) 4045 4046 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 4047 addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 4048 bsr.l _imem_read_long # fetch the instruction words 4049 mov.l %d0,EXC_OPWORD(%a6) 4050 4051############################################################################ 4052 4053 fmov.l &0x0,%fpcr # clear FPCR 4054 fmov.l &0x0,%fpsr # clear FPSR 4055 4056 clr.b SPCOND_FLG(%a6) # clear "special case" flag 4057 4058# Divide the fp instructions into 8 types based on the TYPE field in 4059# bits 6-8 of the opword(classes 6,7 are undefined). 4060# (for the '060, only two types can take this exception) 4061# bftst %d0{&7:&3} # test TYPE 4062 btst &22,%d0 # type 0 or 1 ? 4063 bne.w funimp_misc # type 1 4064 4065######################################### 4066# TYPE == 0: General instructions # 4067######################################### 4068funimp_gen: 4069 4070 clr.b STORE_FLG(%a6) # clear "store result" flag 4071 4072# clear the ccode byte and exception status byte 4073 andi.l &0x00ff00ff,USER_FPSR(%a6) 4074 4075 bfextu %d0{&16:&6},%d1 # extract upper 6 of cmdreg 4076 cmpi.b %d1,&0x17 # is op an fmovecr? 4077 beq.w funimp_fmovcr # yes 4078 4079funimp_gen_op: 4080 bsr.l _load_fop # load 4081 4082 clr.l %d0 4083 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode 4084 4085 mov.b 1+EXC_CMDREG(%a6),%d1 4086 andi.w &0x003f,%d1 # extract extension bits 4087 lsl.w &0x3,%d1 # shift right 3 bits 4088 or.b STAG(%a6),%d1 # insert src optag bits 4089 4090 lea FP_DST(%a6),%a1 # pass dst ptr in a1 4091 lea FP_SRC(%a6),%a0 # pass src ptr in a0 4092 4093 mov.w (tbl_trans.w,%pc,%d1.w*2),%d1 4094 jsr (tbl_trans.w,%pc,%d1.w*1) # emulate 4095 4096funimp_fsave: 4097 mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled 4098 bne.w funimp_ena # some are enabled 4099 4100funimp_store: 4101 bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch Dn 4102 bsr.l store_fpreg # store result to fp regfile 4103 4104funimp_gen_exit: 4105 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 4106 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 4107 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 4108 4109funimp_gen_exit_cmp: 4110 cmpi.b SPCOND_FLG(%a6),&mia7_flg # was the ea mode (sp)+ ? 4111 beq.b funimp_gen_exit_a7 # yes 4112 4113 cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the ea mode -(sp) ? 4114 beq.b funimp_gen_exit_a7 # yes 4115 4116funimp_gen_exit_cont: 4117 unlk %a6 4118 4119funimp_gen_exit_cont2: 4120 btst &0x7,(%sp) # is trace on? 4121 beq.l _fpsp_done # no 4122 4123# this catches a problem with the case where an exception will be re-inserted 4124# into the machine. the frestore has already been executed...so, the fmov.l 4125# alone of the control register would trigger an unwanted exception. 4126# until I feel like fixing this, we'll sidestep the exception. 4127 fsave -(%sp) 4128 fmov.l %fpiar,0x14(%sp) # "Current PC" is in FPIAR 4129 frestore (%sp)+ 4130 mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x24 4131 bra.l _real_trace 4132 4133funimp_gen_exit_a7: 4134 btst &0x5,EXC_SR(%a6) # supervisor or user mode? 4135 bne.b funimp_gen_exit_a7_s # supervisor 4136 4137 mov.l %a0,-(%sp) 4138 mov.l EXC_A7(%a6),%a0 4139 mov.l %a0,%usp 4140 mov.l (%sp)+,%a0 4141 bra.b funimp_gen_exit_cont 4142 4143# if the instruction was executed from supervisor mode and the addressing 4144# mode was (a7)+, then the stack frame for the rte must be shifted "up" 4145# "n" bytes where "n" is the size of the src operand type. 4146# f<op>.{b,w,l,s,d,x,p} 4147funimp_gen_exit_a7_s: 4148 mov.l %d0,-(%sp) # save d0 4149 mov.l EXC_A7(%a6),%d0 # load new a7' 4150 sub.l OLD_A7(%a6),%d0 # subtract old a7' 4151 mov.l 0x2+EXC_PC(%a6),(0x2+EXC_PC,%a6,%d0) # shift stack frame 4152 mov.l EXC_SR(%a6),(EXC_SR,%a6,%d0) # shift stack frame 4153 mov.w %d0,EXC_SR(%a6) # store incr number 4154 mov.l (%sp)+,%d0 # restore d0 4155 4156 unlk %a6 4157 4158 add.w (%sp),%sp # stack frame shifted 4159 bra.b funimp_gen_exit_cont2 4160 4161###################### 4162# fmovecr.x #ccc,fpn # 4163###################### 4164funimp_fmovcr: 4165 clr.l %d0 4166 mov.b FPCR_MODE(%a6),%d0 4167 mov.b 1+EXC_CMDREG(%a6),%d1 4168 andi.l &0x0000007f,%d1 # pass rom offset in d1 4169 bsr.l smovcr 4170 bra.w funimp_fsave 4171 4172######################################################################### 4173 4174# 4175# the user has enabled some exceptions. we figure not to see this too 4176# often so that's why it gets lower priority. 4177# 4178funimp_ena: 4179 4180# was an exception set that was also enabled? 4181 and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled and set 4182 bfffo %d0{&24:&8},%d0 # find highest priority exception 4183 bne.b funimp_exc # at least one was set 4184 4185# no exception that was enabled was set BUT if we got an exact overflow 4186# and overflow wasn't enabled but inexact was (yech!) then this is 4187# an inexact exception; otherwise, return to normal non-exception flow. 4188 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur? 4189 beq.w funimp_store # no; return to normal flow 4190 4191# the overflow w/ exact result happened but was inexact set in the FPCR? 4192funimp_ovfl: 4193 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled? 4194 beq.w funimp_store # no; return to normal flow 4195 bra.b funimp_exc_ovfl # yes 4196 4197# some exception happened that was actually enabled. 4198# we'll insert this new exception into the FPU and then return. 4199funimp_exc: 4200 subi.l &24,%d0 # fix offset to be 0-8 4201 cmpi.b %d0,&0x6 # is exception INEX? 4202 bne.b funimp_exc_force # no 4203 4204# the enabled exception was inexact. so, if it occurs with an overflow 4205# or underflow that was disabled, then we have to force an overflow or 4206# underflow frame. the eventual overflow or underflow handler will see that 4207# it's actually an inexact and act appropriately. this is the only easy 4208# way to have the EXOP available for the enabled inexact handler when 4209# a disabled overflow or underflow has also happened. 4210 btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur? 4211 bne.b funimp_exc_ovfl # yes 4212 btst &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur? 4213 bne.b funimp_exc_unfl # yes 4214 4215# force the fsave exception status bits to signal an exception of the 4216# appropriate type. don't forget to "skew" the source operand in case we 4217# "unskewed" the one the hardware initially gave us. 4218funimp_exc_force: 4219 mov.l %d0,-(%sp) # save d0 4220 bsr.l funimp_skew # check for special case 4221 mov.l (%sp)+,%d0 # restore d0 4222 mov.w (tbl_funimp_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) 4223 bra.b funimp_gen_exit2 # exit with frestore 4224 4225tbl_funimp_except: 4226 short 0xe002, 0xe006, 0xe004, 0xe005 4227 short 0xe003, 0xe002, 0xe001, 0xe001 4228 4229# insert an overflow frame 4230funimp_exc_ovfl: 4231 bsr.l funimp_skew # check for special case 4232 mov.w &0xe005,2+FP_SRC(%a6) 4233 bra.b funimp_gen_exit2 4234 4235# insert an underflow frame 4236funimp_exc_unfl: 4237 bsr.l funimp_skew # check for special case 4238 mov.w &0xe003,2+FP_SRC(%a6) 4239 4240# this is the general exit point for an enabled exception that will be 4241# restored into the machine for the instruction just emulated. 4242funimp_gen_exit2: 4243 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 4244 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 4245 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 4246 4247 frestore FP_SRC(%a6) # insert exceptional status 4248 4249 bra.w funimp_gen_exit_cmp 4250 4251############################################################################ 4252 4253# 4254# TYPE == 1: FDB<cc>, FS<cc>, FTRAP<cc> 4255# 4256# These instructions were implemented on the '881/2 and '040 in hardware but 4257# are emulated in software on the '060. 4258# 4259funimp_misc: 4260 bfextu %d0{&10:&3},%d1 # extract mode field 4261 cmpi.b %d1,&0x1 # is it an fdb<cc>? 4262 beq.w funimp_fdbcc # yes 4263 cmpi.b %d1,&0x7 # is it an fs<cc>? 4264 bne.w funimp_fscc # yes 4265 bfextu %d0{&13:&3},%d1 4266 cmpi.b %d1,&0x2 # is it an fs<cc>? 4267 blt.w funimp_fscc # yes 4268 4269######################### 4270# ftrap<cc> # 4271# ftrap<cc>.w #<data> # 4272# ftrap<cc>.l #<data> # 4273######################### 4274funimp_ftrapcc: 4275 4276 bsr.l _ftrapcc # FTRAP<cc>() 4277 4278 cmpi.b SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring? 4279 beq.w funimp_bsun # yes 4280 4281 cmpi.b SPCOND_FLG(%a6),&ftrapcc_flg # should a trap occur? 4282 bne.w funimp_done # no 4283 4284# FP UNIMP FRAME TRAP FRAME 4285# ***************** ***************** 4286# ** <EA> ** ** Current PC ** 4287# ***************** ***************** 4288# * 0x2 * 0x02c * * 0x2 * 0x01c * 4289# ***************** ***************** 4290# ** Next PC ** ** Next PC ** 4291# ***************** ***************** 4292# * SR * * SR * 4293# ***************** ***************** 4294# (6 words) (6 words) 4295# 4296# the ftrapcc instruction should take a trap. so, here we must create a 4297# trap stack frame from an unimplemented fp instruction stack frame and 4298# jump to the user supplied entry point for the trap exception 4299funimp_ftrapcc_tp: 4300 mov.l USER_FPIAR(%a6),EXC_EA(%a6) # Address = Current PC 4301 mov.w &0x201c,EXC_VOFF(%a6) # Vector Offset = 0x01c 4302 4303 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 4304 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 4305 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 4306 4307 unlk %a6 4308 bra.l _real_trap 4309 4310######################### 4311# fdb<cc> Dn,<label> # 4312######################### 4313funimp_fdbcc: 4314 4315 mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 4316 addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 4317 bsr.l _imem_read_word # read displacement 4318 4319 tst.l %d1 # did ifetch fail? 4320 bne.w funimp_iacc # yes 4321 4322 ext.l %d0 # sign extend displacement 4323 4324 bsr.l _fdbcc # FDB<cc>() 4325 4326 cmpi.b SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring? 4327 beq.w funimp_bsun 4328 4329 bra.w funimp_done # branch to finish 4330 4331################# 4332# fs<cc>.b <ea> # 4333################# 4334funimp_fscc: 4335 4336 bsr.l _fscc # FS<cc>() 4337 4338# I am assuming here that an "fs<cc>.b -(An)" or "fs<cc>.b (An)+" instruction 4339# does not need to update "An" before taking a bsun exception. 4340 cmpi.b SPCOND_FLG(%a6),&fbsun_flg # is enabled bsun occurring? 4341 beq.w funimp_bsun 4342 4343 btst &0x5,EXC_SR(%a6) # yes; is it a user mode exception? 4344 bne.b funimp_fscc_s # no 4345 4346funimp_fscc_u: 4347 mov.l EXC_A7(%a6),%a0 # yes; set new USP 4348 mov.l %a0,%usp 4349 bra.w funimp_done # branch to finish 4350 4351# remember, I'm assuming that post-increment is bogus...(it IS!!!) 4352# so, the least significant WORD of the stacked effective address got 4353# overwritten by the "fs<cc> -(An)". We must shift the stack frame "down" 4354# so that the rte will work correctly without destroying the result. 4355# even though the operation size is byte, the stack ptr is decr by 2. 4356# 4357# remember, also, this instruction may be traced. 4358funimp_fscc_s: 4359 cmpi.b SPCOND_FLG(%a6),&mda7_flg # was a7 modified? 4360 bne.w funimp_done # no 4361 4362 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 4363 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 4364 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 4365 4366 unlk %a6 4367 4368 btst &0x7,(%sp) # is trace enabled? 4369 bne.b funimp_fscc_s_trace # yes 4370 4371 subq.l &0x2,%sp 4372 mov.l 0x2(%sp),(%sp) # shift SR,hi(PC) "down" 4373 mov.l 0x6(%sp),0x4(%sp) # shift lo(PC),voff "down" 4374 bra.l _fpsp_done 4375 4376funimp_fscc_s_trace: 4377 subq.l &0x2,%sp 4378 mov.l 0x2(%sp),(%sp) # shift SR,hi(PC) "down" 4379 mov.w 0x6(%sp),0x4(%sp) # shift lo(PC) 4380 mov.w &0x2024,0x6(%sp) # fmt/voff = $2024 4381 fmov.l %fpiar,0x8(%sp) # insert "current PC" 4382 4383 bra.l _real_trace 4384 4385# 4386# The ftrap<cc>, fs<cc>, or fdb<cc> is to take an enabled bsun. we must convert 4387# the fp unimplemented instruction exception stack frame into a bsun stack frame, 4388# restore a bsun exception into the machine, and branch to the user 4389# supplied bsun hook. 4390# 4391# FP UNIMP FRAME BSUN FRAME 4392# ***************** ***************** 4393# ** <EA> ** * 0x0 * 0x0c0 * 4394# ***************** ***************** 4395# * 0x2 * 0x02c * ** Current PC ** 4396# ***************** ***************** 4397# ** Next PC ** * SR * 4398# ***************** ***************** 4399# * SR * (4 words) 4400# ***************** 4401# (6 words) 4402# 4403funimp_bsun: 4404 mov.w &0x00c0,2+EXC_EA(%a6) # Fmt = 0x0; Vector Offset = 0x0c0 4405 mov.l USER_FPIAR(%a6),EXC_VOFF(%a6) # PC = Current PC 4406 mov.w EXC_SR(%a6),2+EXC_PC(%a6) # shift SR "up" 4407 4408 mov.w &0xe000,2+FP_SRC(%a6) # bsun exception enabled 4409 4410 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 4411 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 4412 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 4413 4414 frestore FP_SRC(%a6) # restore bsun exception 4415 4416 unlk %a6 4417 4418 addq.l &0x4,%sp # erase sludge 4419 4420 bra.l _real_bsun # branch to user bsun hook 4421 4422# 4423# all ftrapcc/fscc/fdbcc processing has been completed. unwind the stack frame 4424# and return. 4425# 4426# as usual, we have to check for trace mode being on here. since instructions 4427# modifying the supervisor stack frame don't pass through here, this is a 4428# relatively easy task. 4429# 4430funimp_done: 4431 fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1 4432 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 4433 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 4434 4435 unlk %a6 4436 4437 btst &0x7,(%sp) # is trace enabled? 4438 bne.b funimp_trace # yes 4439 4440 bra.l _fpsp_done 4441 4442# FP UNIMP FRAME TRACE FRAME 4443# ***************** ***************** 4444# ** <EA> ** ** Current PC ** 4445# ***************** ***************** 4446# * 0x2 * 0x02c * * 0x2 * 0x024 * 4447# ***************** ***************** 4448# ** Next PC ** ** Next PC ** 4449# ***************** ***************** 4450# * SR * * SR * 4451# ***************** ***************** 4452# (6 words) (6 words) 4453# 4454# the fscc instruction should take a trace trap. so, here we must create a 4455# trace stack frame from an unimplemented fp instruction stack frame and 4456# jump to the user supplied entry point for the trace exception 4457funimp_trace: 4458 fmov.l %fpiar,0x8(%sp) # current PC is in fpiar 4459 mov.b &0x24,0x7(%sp) # vector offset = 0x024 4460 4461 bra.l _real_trace 4462 4463################################################################ 4464 4465 global tbl_trans 4466 swbeg &0x1c0 4467tbl_trans: 4468 short tbl_trans - tbl_trans # $00-0 fmovecr all 4469 short tbl_trans - tbl_trans # $00-1 fmovecr all 4470 short tbl_trans - tbl_trans # $00-2 fmovecr all 4471 short tbl_trans - tbl_trans # $00-3 fmovecr all 4472 short tbl_trans - tbl_trans # $00-4 fmovecr all 4473 short tbl_trans - tbl_trans # $00-5 fmovecr all 4474 short tbl_trans - tbl_trans # $00-6 fmovecr all 4475 short tbl_trans - tbl_trans # $00-7 fmovecr all 4476 4477 short tbl_trans - tbl_trans # $01-0 fint norm 4478 short tbl_trans - tbl_trans # $01-1 fint zero 4479 short tbl_trans - tbl_trans # $01-2 fint inf 4480 short tbl_trans - tbl_trans # $01-3 fint qnan 4481 short tbl_trans - tbl_trans # $01-5 fint denorm 4482 short tbl_trans - tbl_trans # $01-4 fint snan 4483 short tbl_trans - tbl_trans # $01-6 fint unnorm 4484 short tbl_trans - tbl_trans # $01-7 ERROR 4485 4486 short ssinh - tbl_trans # $02-0 fsinh norm 4487 short src_zero - tbl_trans # $02-1 fsinh zero 4488 short src_inf - tbl_trans # $02-2 fsinh inf 4489 short src_qnan - tbl_trans # $02-3 fsinh qnan 4490 short ssinhd - tbl_trans # $02-5 fsinh denorm 4491 short src_snan - tbl_trans # $02-4 fsinh snan 4492 short tbl_trans - tbl_trans # $02-6 fsinh unnorm 4493 short tbl_trans - tbl_trans # $02-7 ERROR 4494 4495 short tbl_trans - tbl_trans # $03-0 fintrz norm 4496 short tbl_trans - tbl_trans # $03-1 fintrz zero 4497 short tbl_trans - tbl_trans # $03-2 fintrz inf 4498 short tbl_trans - tbl_trans # $03-3 fintrz qnan 4499 short tbl_trans - tbl_trans # $03-5 fintrz denorm 4500 short tbl_trans - tbl_trans # $03-4 fintrz snan 4501 short tbl_trans - tbl_trans # $03-6 fintrz unnorm 4502 short tbl_trans - tbl_trans # $03-7 ERROR 4503 4504 short tbl_trans - tbl_trans # $04-0 fsqrt norm 4505 short tbl_trans - tbl_trans # $04-1 fsqrt zero 4506 short tbl_trans - tbl_trans # $04-2 fsqrt inf 4507 short tbl_trans - tbl_trans # $04-3 fsqrt qnan 4508 short tbl_trans - tbl_trans # $04-5 fsqrt denorm 4509 short tbl_trans - tbl_trans # $04-4 fsqrt snan 4510 short tbl_trans - tbl_trans # $04-6 fsqrt unnorm 4511 short tbl_trans - tbl_trans # $04-7 ERROR 4512 4513 short tbl_trans - tbl_trans # $05-0 ERROR 4514 short tbl_trans - tbl_trans # $05-1 ERROR 4515 short tbl_trans - tbl_trans # $05-2 ERROR 4516 short tbl_trans - tbl_trans # $05-3 ERROR 4517 short tbl_trans - tbl_trans # $05-4 ERROR 4518 short tbl_trans - tbl_trans # $05-5 ERROR 4519 short tbl_trans - tbl_trans # $05-6 ERROR 4520 short tbl_trans - tbl_trans # $05-7 ERROR 4521 4522 short slognp1 - tbl_trans # $06-0 flognp1 norm 4523 short src_zero - tbl_trans # $06-1 flognp1 zero 4524 short sopr_inf - tbl_trans # $06-2 flognp1 inf 4525 short src_qnan - tbl_trans # $06-3 flognp1 qnan 4526 short slognp1d - tbl_trans # $06-5 flognp1 denorm 4527 short src_snan - tbl_trans # $06-4 flognp1 snan 4528 short tbl_trans - tbl_trans # $06-6 flognp1 unnorm 4529 short tbl_trans - tbl_trans # $06-7 ERROR 4530 4531 short tbl_trans - tbl_trans # $07-0 ERROR 4532 short tbl_trans - tbl_trans # $07-1 ERROR 4533 short tbl_trans - tbl_trans # $07-2 ERROR 4534 short tbl_trans - tbl_trans # $07-3 ERROR 4535 short tbl_trans - tbl_trans # $07-4 ERROR 4536 short tbl_trans - tbl_trans # $07-5 ERROR 4537 short tbl_trans - tbl_trans # $07-6 ERROR 4538 short tbl_trans - tbl_trans # $07-7 ERROR 4539 4540 short setoxm1 - tbl_trans # $08-0 fetoxm1 norm 4541 short src_zero - tbl_trans # $08-1 fetoxm1 zero 4542 short setoxm1i - tbl_trans # $08-2 fetoxm1 inf 4543 short src_qnan - tbl_trans # $08-3 fetoxm1 qnan 4544 short setoxm1d - tbl_trans # $08-5 fetoxm1 denorm 4545 short src_snan - tbl_trans # $08-4 fetoxm1 snan 4546 short tbl_trans - tbl_trans # $08-6 fetoxm1 unnorm 4547 short tbl_trans - tbl_trans # $08-7 ERROR 4548 4549 short stanh - tbl_trans # $09-0 ftanh norm 4550 short src_zero - tbl_trans # $09-1 ftanh zero 4551 short src_one - tbl_trans # $09-2 ftanh inf 4552 short src_qnan - tbl_trans # $09-3 ftanh qnan 4553 short stanhd - tbl_trans # $09-5 ftanh denorm 4554 short src_snan - tbl_trans # $09-4 ftanh snan 4555 short tbl_trans - tbl_trans # $09-6 ftanh unnorm 4556 short tbl_trans - tbl_trans # $09-7 ERROR 4557 4558 short satan - tbl_trans # $0a-0 fatan norm 4559 short src_zero - tbl_trans # $0a-1 fatan zero 4560 short spi_2 - tbl_trans # $0a-2 fatan inf 4561 short src_qnan - tbl_trans # $0a-3 fatan qnan 4562 short satand - tbl_trans # $0a-5 fatan denorm 4563 short src_snan - tbl_trans # $0a-4 fatan snan 4564 short tbl_trans - tbl_trans # $0a-6 fatan unnorm 4565 short tbl_trans - tbl_trans # $0a-7 ERROR 4566 4567 short tbl_trans - tbl_trans # $0b-0 ERROR 4568 short tbl_trans - tbl_trans # $0b-1 ERROR 4569 short tbl_trans - tbl_trans # $0b-2 ERROR 4570 short tbl_trans - tbl_trans # $0b-3 ERROR 4571 short tbl_trans - tbl_trans # $0b-4 ERROR 4572 short tbl_trans - tbl_trans # $0b-5 ERROR 4573 short tbl_trans - tbl_trans # $0b-6 ERROR 4574 short tbl_trans - tbl_trans # $0b-7 ERROR 4575 4576 short sasin - tbl_trans # $0c-0 fasin norm 4577 short src_zero - tbl_trans # $0c-1 fasin zero 4578 short t_operr - tbl_trans # $0c-2 fasin inf 4579 short src_qnan - tbl_trans # $0c-3 fasin qnan 4580 short sasind - tbl_trans # $0c-5 fasin denorm 4581 short src_snan - tbl_trans # $0c-4 fasin snan 4582 short tbl_trans - tbl_trans # $0c-6 fasin unnorm 4583 short tbl_trans - tbl_trans # $0c-7 ERROR 4584 4585 short satanh - tbl_trans # $0d-0 fatanh norm 4586 short src_zero - tbl_trans # $0d-1 fatanh zero 4587 short t_operr - tbl_trans # $0d-2 fatanh inf 4588 short src_qnan - tbl_trans # $0d-3 fatanh qnan 4589 short satanhd - tbl_trans # $0d-5 fatanh denorm 4590 short src_snan - tbl_trans # $0d-4 fatanh snan 4591 short tbl_trans - tbl_trans # $0d-6 fatanh unnorm 4592 short tbl_trans - tbl_trans # $0d-7 ERROR 4593 4594 short ssin - tbl_trans # $0e-0 fsin norm 4595 short src_zero - tbl_trans # $0e-1 fsin zero 4596 short t_operr - tbl_trans # $0e-2 fsin inf 4597 short src_qnan - tbl_trans # $0e-3 fsin qnan 4598 short ssind - tbl_trans # $0e-5 fsin denorm 4599 short src_snan - tbl_trans # $0e-4 fsin snan 4600 short tbl_trans - tbl_trans # $0e-6 fsin unnorm 4601 short tbl_trans - tbl_trans # $0e-7 ERROR 4602 4603 short stan - tbl_trans # $0f-0 ftan norm 4604 short src_zero - tbl_trans # $0f-1 ftan zero 4605 short t_operr - tbl_trans # $0f-2 ftan inf 4606 short src_qnan - tbl_trans # $0f-3 ftan qnan 4607 short stand - tbl_trans # $0f-5 ftan denorm 4608 short src_snan - tbl_trans # $0f-4 ftan snan 4609 short tbl_trans - tbl_trans # $0f-6 ftan unnorm 4610 short tbl_trans - tbl_trans # $0f-7 ERROR 4611 4612 short setox - tbl_trans # $10-0 fetox norm 4613 short ld_pone - tbl_trans # $10-1 fetox zero 4614 short szr_inf - tbl_trans # $10-2 fetox inf 4615 short src_qnan - tbl_trans # $10-3 fetox qnan 4616 short setoxd - tbl_trans # $10-5 fetox denorm 4617 short src_snan - tbl_trans # $10-4 fetox snan 4618 short tbl_trans - tbl_trans # $10-6 fetox unnorm 4619 short tbl_trans - tbl_trans # $10-7 ERROR 4620 4621 short stwotox - tbl_trans # $11-0 ftwotox norm 4622 short ld_pone - tbl_trans # $11-1 ftwotox zero 4623 short szr_inf - tbl_trans # $11-2 ftwotox inf 4624 short src_qnan - tbl_trans # $11-3 ftwotox qnan 4625 short stwotoxd - tbl_trans # $11-5 ftwotox denorm 4626 short src_snan - tbl_trans # $11-4 ftwotox snan 4627 short tbl_trans - tbl_trans # $11-6 ftwotox unnorm 4628 short tbl_trans - tbl_trans # $11-7 ERROR 4629 4630 short stentox - tbl_trans # $12-0 ftentox norm 4631 short ld_pone - tbl_trans # $12-1 ftentox zero 4632 short szr_inf - tbl_trans # $12-2 ftentox inf 4633 short src_qnan - tbl_trans # $12-3 ftentox qnan 4634 short stentoxd - tbl_trans # $12-5 ftentox denorm 4635 short src_snan - tbl_trans # $12-4 ftentox snan 4636 short tbl_trans - tbl_trans # $12-6 ftentox unnorm 4637 short tbl_trans - tbl_trans # $12-7 ERROR 4638 4639 short tbl_trans - tbl_trans # $13-0 ERROR 4640 short tbl_trans - tbl_trans # $13-1 ERROR 4641 short tbl_trans - tbl_trans # $13-2 ERROR 4642 short tbl_trans - tbl_trans # $13-3 ERROR 4643 short tbl_trans - tbl_trans # $13-4 ERROR 4644 short tbl_trans - tbl_trans # $13-5 ERROR 4645 short tbl_trans - tbl_trans # $13-6 ERROR 4646 short tbl_trans - tbl_trans # $13-7 ERROR 4647 4648 short slogn - tbl_trans # $14-0 flogn norm 4649 short t_dz2 - tbl_trans # $14-1 flogn zero 4650 short sopr_inf - tbl_trans # $14-2 flogn inf 4651 short src_qnan - tbl_trans # $14-3 flogn qnan 4652 short slognd - tbl_trans # $14-5 flogn denorm 4653 short src_snan - tbl_trans # $14-4 flogn snan 4654 short tbl_trans - tbl_trans # $14-6 flogn unnorm 4655 short tbl_trans - tbl_trans # $14-7 ERROR 4656 4657 short slog10 - tbl_trans # $15-0 flog10 norm 4658 short t_dz2 - tbl_trans # $15-1 flog10 zero 4659 short sopr_inf - tbl_trans # $15-2 flog10 inf 4660 short src_qnan - tbl_trans # $15-3 flog10 qnan 4661 short slog10d - tbl_trans # $15-5 flog10 denorm 4662 short src_snan - tbl_trans # $15-4 flog10 snan 4663 short tbl_trans - tbl_trans # $15-6 flog10 unnorm 4664 short tbl_trans - tbl_trans # $15-7 ERROR 4665 4666 short slog2 - tbl_trans # $16-0 flog2 norm 4667 short t_dz2 - tbl_trans # $16-1 flog2 zero 4668 short sopr_inf - tbl_trans # $16-2 flog2 inf 4669 short src_qnan - tbl_trans # $16-3 flog2 qnan 4670 short slog2d - tbl_trans # $16-5 flog2 denorm 4671 short src_snan - tbl_trans # $16-4 flog2 snan 4672 short tbl_trans - tbl_trans # $16-6 flog2 unnorm 4673 short tbl_trans - tbl_trans # $16-7 ERROR 4674 4675 short tbl_trans - tbl_trans # $17-0 ERROR 4676 short tbl_trans - tbl_trans # $17-1 ERROR 4677 short tbl_trans - tbl_trans # $17-2 ERROR 4678 short tbl_trans - tbl_trans # $17-3 ERROR 4679 short tbl_trans - tbl_trans # $17-4 ERROR 4680 short tbl_trans - tbl_trans # $17-5 ERROR 4681 short tbl_trans - tbl_trans # $17-6 ERROR 4682 short tbl_trans - tbl_trans # $17-7 ERROR 4683 4684 short tbl_trans - tbl_trans # $18-0 fabs norm 4685 short tbl_trans - tbl_trans # $18-1 fabs zero 4686 short tbl_trans - tbl_trans # $18-2 fabs inf 4687 short tbl_trans - tbl_trans # $18-3 fabs qnan 4688 short tbl_trans - tbl_trans # $18-5 fabs denorm 4689 short tbl_trans - tbl_trans # $18-4 fabs snan 4690 short tbl_trans - tbl_trans # $18-6 fabs unnorm 4691 short tbl_trans - tbl_trans # $18-7 ERROR 4692 4693 short scosh - tbl_trans # $19-0 fcosh norm 4694 short ld_pone - tbl_trans # $19-1 fcosh zero 4695 short ld_pinf - tbl_trans # $19-2 fcosh inf 4696 short src_qnan - tbl_trans # $19-3 fcosh qnan 4697 short scoshd - tbl_trans # $19-5 fcosh denorm 4698 short src_snan - tbl_trans # $19-4 fcosh snan 4699 short tbl_trans - tbl_trans # $19-6 fcosh unnorm 4700 short tbl_trans - tbl_trans # $19-7 ERROR 4701 4702 short tbl_trans - tbl_trans # $1a-0 fneg norm 4703 short tbl_trans - tbl_trans # $1a-1 fneg zero 4704 short tbl_trans - tbl_trans # $1a-2 fneg inf 4705 short tbl_trans - tbl_trans # $1a-3 fneg qnan 4706 short tbl_trans - tbl_trans # $1a-5 fneg denorm 4707 short tbl_trans - tbl_trans # $1a-4 fneg snan 4708 short tbl_trans - tbl_trans # $1a-6 fneg unnorm 4709 short tbl_trans - tbl_trans # $1a-7 ERROR 4710 4711 short tbl_trans - tbl_trans # $1b-0 ERROR 4712 short tbl_trans - tbl_trans # $1b-1 ERROR 4713 short tbl_trans - tbl_trans # $1b-2 ERROR 4714 short tbl_trans - tbl_trans # $1b-3 ERROR 4715 short tbl_trans - tbl_trans # $1b-4 ERROR 4716 short tbl_trans - tbl_trans # $1b-5 ERROR 4717 short tbl_trans - tbl_trans # $1b-6 ERROR 4718 short tbl_trans - tbl_trans # $1b-7 ERROR 4719 4720 short sacos - tbl_trans # $1c-0 facos norm 4721 short ld_ppi2 - tbl_trans # $1c-1 facos zero 4722 short t_operr - tbl_trans # $1c-2 facos inf 4723 short src_qnan - tbl_trans # $1c-3 facos qnan 4724 short sacosd - tbl_trans # $1c-5 facos denorm 4725 short src_snan - tbl_trans # $1c-4 facos snan 4726 short tbl_trans - tbl_trans # $1c-6 facos unnorm 4727 short tbl_trans - tbl_trans # $1c-7 ERROR 4728 4729 short scos - tbl_trans # $1d-0 fcos norm 4730 short ld_pone - tbl_trans # $1d-1 fcos zero 4731 short t_operr - tbl_trans # $1d-2 fcos inf 4732 short src_qnan - tbl_trans # $1d-3 fcos qnan 4733 short scosd - tbl_trans # $1d-5 fcos denorm 4734 short src_snan - tbl_trans # $1d-4 fcos snan 4735 short tbl_trans - tbl_trans # $1d-6 fcos unnorm 4736 short tbl_trans - tbl_trans # $1d-7 ERROR 4737 4738 short sgetexp - tbl_trans # $1e-0 fgetexp norm 4739 short src_zero - tbl_trans # $1e-1 fgetexp zero 4740 short t_operr - tbl_trans # $1e-2 fgetexp inf 4741 short src_qnan - tbl_trans # $1e-3 fgetexp qnan 4742 short sgetexpd - tbl_trans # $1e-5 fgetexp denorm 4743 short src_snan - tbl_trans # $1e-4 fgetexp snan 4744 short tbl_trans - tbl_trans # $1e-6 fgetexp unnorm 4745 short tbl_trans - tbl_trans # $1e-7 ERROR 4746 4747 short sgetman - tbl_trans # $1f-0 fgetman norm 4748 short src_zero - tbl_trans # $1f-1 fgetman zero 4749 short t_operr - tbl_trans # $1f-2 fgetman inf 4750 short src_qnan - tbl_trans # $1f-3 fgetman qnan 4751 short sgetmand - tbl_trans # $1f-5 fgetman denorm 4752 short src_snan - tbl_trans # $1f-4 fgetman snan 4753 short tbl_trans - tbl_trans # $1f-6 fgetman unnorm 4754 short tbl_trans - tbl_trans # $1f-7 ERROR 4755 4756 short tbl_trans - tbl_trans # $20-0 fdiv norm 4757 short tbl_trans - tbl_trans # $20-1 fdiv zero 4758 short tbl_trans - tbl_trans # $20-2 fdiv inf 4759 short tbl_trans - tbl_trans # $20-3 fdiv qnan 4760 short tbl_trans - tbl_trans # $20-5 fdiv denorm 4761 short tbl_trans - tbl_trans # $20-4 fdiv snan 4762 short tbl_trans - tbl_trans # $20-6 fdiv unnorm 4763 short tbl_trans - tbl_trans # $20-7 ERROR 4764 4765 short smod_snorm - tbl_trans # $21-0 fmod norm 4766 short smod_szero - tbl_trans # $21-1 fmod zero 4767 short smod_sinf - tbl_trans # $21-2 fmod inf 4768 short sop_sqnan - tbl_trans # $21-3 fmod qnan 4769 short smod_sdnrm - tbl_trans # $21-5 fmod denorm 4770 short sop_ssnan - tbl_trans # $21-4 fmod snan 4771 short tbl_trans - tbl_trans # $21-6 fmod unnorm 4772 short tbl_trans - tbl_trans # $21-7 ERROR 4773 4774 short tbl_trans - tbl_trans # $22-0 fadd norm 4775 short tbl_trans - tbl_trans # $22-1 fadd zero 4776 short tbl_trans - tbl_trans # $22-2 fadd inf 4777 short tbl_trans - tbl_trans # $22-3 fadd qnan 4778 short tbl_trans - tbl_trans # $22-5 fadd denorm 4779 short tbl_trans - tbl_trans # $22-4 fadd snan 4780 short tbl_trans - tbl_trans # $22-6 fadd unnorm 4781 short tbl_trans - tbl_trans # $22-7 ERROR 4782 4783 short tbl_trans - tbl_trans # $23-0 fmul norm 4784 short tbl_trans - tbl_trans # $23-1 fmul zero 4785 short tbl_trans - tbl_trans # $23-2 fmul inf 4786 short tbl_trans - tbl_trans # $23-3 fmul qnan 4787 short tbl_trans - tbl_trans # $23-5 fmul denorm 4788 short tbl_trans - tbl_trans # $23-4 fmul snan 4789 short tbl_trans - tbl_trans # $23-6 fmul unnorm 4790 short tbl_trans - tbl_trans # $23-7 ERROR 4791 4792 short tbl_trans - tbl_trans # $24-0 fsgldiv norm 4793 short tbl_trans - tbl_trans # $24-1 fsgldiv zero 4794 short tbl_trans - tbl_trans # $24-2 fsgldiv inf 4795 short tbl_trans - tbl_trans # $24-3 fsgldiv qnan 4796 short tbl_trans - tbl_trans # $24-5 fsgldiv denorm 4797 short tbl_trans - tbl_trans # $24-4 fsgldiv snan 4798 short tbl_trans - tbl_trans # $24-6 fsgldiv unnorm 4799 short tbl_trans - tbl_trans # $24-7 ERROR 4800 4801 short srem_snorm - tbl_trans # $25-0 frem norm 4802 short srem_szero - tbl_trans # $25-1 frem zero 4803 short srem_sinf - tbl_trans # $25-2 frem inf 4804 short sop_sqnan - tbl_trans # $25-3 frem qnan 4805 short srem_sdnrm - tbl_trans # $25-5 frem denorm 4806 short sop_ssnan - tbl_trans # $25-4 frem snan 4807 short tbl_trans - tbl_trans # $25-6 frem unnorm 4808 short tbl_trans - tbl_trans # $25-7 ERROR 4809 4810 short sscale_snorm - tbl_trans # $26-0 fscale norm 4811 short sscale_szero - tbl_trans # $26-1 fscale zero 4812 short sscale_sinf - tbl_trans # $26-2 fscale inf 4813 short sop_sqnan - tbl_trans # $26-3 fscale qnan 4814 short sscale_sdnrm - tbl_trans # $26-5 fscale denorm 4815 short sop_ssnan - tbl_trans # $26-4 fscale snan 4816 short tbl_trans - tbl_trans # $26-6 fscale unnorm 4817 short tbl_trans - tbl_trans # $26-7 ERROR 4818 4819 short tbl_trans - tbl_trans # $27-0 fsglmul norm 4820 short tbl_trans - tbl_trans # $27-1 fsglmul zero 4821 short tbl_trans - tbl_trans # $27-2 fsglmul inf 4822 short tbl_trans - tbl_trans # $27-3 fsglmul qnan 4823 short tbl_trans - tbl_trans # $27-5 fsglmul denorm 4824 short tbl_trans - tbl_trans # $27-4 fsglmul snan 4825 short tbl_trans - tbl_trans # $27-6 fsglmul unnorm 4826 short tbl_trans - tbl_trans # $27-7 ERROR 4827 4828 short tbl_trans - tbl_trans # $28-0 fsub norm 4829 short tbl_trans - tbl_trans # $28-1 fsub zero 4830 short tbl_trans - tbl_trans # $28-2 fsub inf 4831 short tbl_trans - tbl_trans # $28-3 fsub qnan 4832 short tbl_trans - tbl_trans # $28-5 fsub denorm 4833 short tbl_trans - tbl_trans # $28-4 fsub snan 4834 short tbl_trans - tbl_trans # $28-6 fsub unnorm 4835 short tbl_trans - tbl_trans # $28-7 ERROR 4836 4837 short tbl_trans - tbl_trans # $29-0 ERROR 4838 short tbl_trans - tbl_trans # $29-1 ERROR 4839 short tbl_trans - tbl_trans # $29-2 ERROR 4840 short tbl_trans - tbl_trans # $29-3 ERROR 4841 short tbl_trans - tbl_trans # $29-4 ERROR 4842 short tbl_trans - tbl_trans # $29-5 ERROR 4843 short tbl_trans - tbl_trans # $29-6 ERROR 4844 short tbl_trans - tbl_trans # $29-7 ERROR 4845 4846 short tbl_trans - tbl_trans # $2a-0 ERROR 4847 short tbl_trans - tbl_trans # $2a-1 ERROR 4848 short tbl_trans - tbl_trans # $2a-2 ERROR 4849 short tbl_trans - tbl_trans # $2a-3 ERROR 4850 short tbl_trans - tbl_trans # $2a-4 ERROR 4851 short tbl_trans - tbl_trans # $2a-5 ERROR 4852 short tbl_trans - tbl_trans # $2a-6 ERROR 4853 short tbl_trans - tbl_trans # $2a-7 ERROR 4854 4855 short tbl_trans - tbl_trans # $2b-0 ERROR 4856 short tbl_trans - tbl_trans # $2b-1 ERROR 4857 short tbl_trans - tbl_trans # $2b-2 ERROR 4858 short tbl_trans - tbl_trans # $2b-3 ERROR 4859 short tbl_trans - tbl_trans # $2b-4 ERROR 4860 short tbl_trans - tbl_trans # $2b-5 ERROR 4861 short tbl_trans - tbl_trans # $2b-6 ERROR 4862 short tbl_trans - tbl_trans # $2b-7 ERROR 4863 4864 short tbl_trans - tbl_trans # $2c-0 ERROR 4865 short tbl_trans - tbl_trans # $2c-1 ERROR 4866 short tbl_trans - tbl_trans # $2c-2 ERROR 4867 short tbl_trans - tbl_trans # $2c-3 ERROR 4868 short tbl_trans - tbl_trans # $2c-4 ERROR 4869 short tbl_trans - tbl_trans # $2c-5 ERROR 4870 short tbl_trans - tbl_trans # $2c-6 ERROR 4871 short tbl_trans - tbl_trans # $2c-7 ERROR 4872 4873 short tbl_trans - tbl_trans # $2d-0 ERROR 4874 short tbl_trans - tbl_trans # $2d-1 ERROR 4875 short tbl_trans - tbl_trans # $2d-2 ERROR 4876 short tbl_trans - tbl_trans # $2d-3 ERROR 4877 short tbl_trans - tbl_trans # $2d-4 ERROR 4878 short tbl_trans - tbl_trans # $2d-5 ERROR 4879 short tbl_trans - tbl_trans # $2d-6 ERROR 4880 short tbl_trans - tbl_trans # $2d-7 ERROR 4881 4882 short tbl_trans - tbl_trans # $2e-0 ERROR 4883 short tbl_trans - tbl_trans # $2e-1 ERROR 4884 short tbl_trans - tbl_trans # $2e-2 ERROR 4885 short tbl_trans - tbl_trans # $2e-3 ERROR 4886 short tbl_trans - tbl_trans # $2e-4 ERROR 4887 short tbl_trans - tbl_trans # $2e-5 ERROR 4888 short tbl_trans - tbl_trans # $2e-6 ERROR 4889 short tbl_trans - tbl_trans # $2e-7 ERROR 4890 4891 short tbl_trans - tbl_trans # $2f-0 ERROR 4892 short tbl_trans - tbl_trans # $2f-1 ERROR 4893 short tbl_trans - tbl_trans # $2f-2 ERROR 4894 short tbl_trans - tbl_trans # $2f-3 ERROR 4895 short tbl_trans - tbl_trans # $2f-4 ERROR 4896 short tbl_trans - tbl_trans # $2f-5 ERROR 4897 short tbl_trans - tbl_trans # $2f-6 ERROR 4898 short tbl_trans - tbl_trans # $2f-7 ERROR 4899 4900 short ssincos - tbl_trans # $30-0 fsincos norm 4901 short ssincosz - tbl_trans # $30-1 fsincos zero 4902 short ssincosi - tbl_trans # $30-2 fsincos inf 4903 short ssincosqnan - tbl_trans # $30-3 fsincos qnan 4904 short ssincosd - tbl_trans # $30-5 fsincos denorm 4905 short ssincossnan - tbl_trans # $30-4 fsincos snan 4906 short tbl_trans - tbl_trans # $30-6 fsincos unnorm 4907 short tbl_trans - tbl_trans # $30-7 ERROR 4908 4909 short ssincos - tbl_trans # $31-0 fsincos norm 4910 short ssincosz - tbl_trans # $31-1 fsincos zero 4911 short ssincosi - tbl_trans # $31-2 fsincos inf 4912 short ssincosqnan - tbl_trans # $31-3 fsincos qnan 4913 short ssincosd - tbl_trans # $31-5 fsincos denorm 4914 short ssincossnan - tbl_trans # $31-4 fsincos snan 4915 short tbl_trans - tbl_trans # $31-6 fsincos unnorm 4916 short tbl_trans - tbl_trans # $31-7 ERROR 4917 4918 short ssincos - tbl_trans # $32-0 fsincos norm 4919 short ssincosz - tbl_trans # $32-1 fsincos zero 4920 short ssincosi - tbl_trans # $32-2 fsincos inf 4921 short ssincosqnan - tbl_trans # $32-3 fsincos qnan 4922 short ssincosd - tbl_trans # $32-5 fsincos denorm 4923 short ssincossnan - tbl_trans # $32-4 fsincos snan 4924 short tbl_trans - tbl_trans # $32-6 fsincos unnorm 4925 short tbl_trans - tbl_trans # $32-7 ERROR 4926 4927 short ssincos - tbl_trans # $33-0 fsincos norm 4928 short ssincosz - tbl_trans # $33-1 fsincos zero 4929 short ssincosi - tbl_trans # $33-2 fsincos inf 4930 short ssincosqnan - tbl_trans # $33-3 fsincos qnan 4931 short ssincosd - tbl_trans # $33-5 fsincos denorm 4932 short ssincossnan - tbl_trans # $33-4 fsincos snan 4933 short tbl_trans - tbl_trans # $33-6 fsincos unnorm 4934 short tbl_trans - tbl_trans # $33-7 ERROR 4935 4936 short ssincos - tbl_trans # $34-0 fsincos norm 4937 short ssincosz - tbl_trans # $34-1 fsincos zero 4938 short ssincosi - tbl_trans # $34-2 fsincos inf 4939 short ssincosqnan - tbl_trans # $34-3 fsincos qnan 4940 short ssincosd - tbl_trans # $34-5 fsincos denorm 4941 short ssincossnan - tbl_trans # $34-4 fsincos snan 4942 short tbl_trans - tbl_trans # $34-6 fsincos unnorm 4943 short tbl_trans - tbl_trans # $34-7 ERROR 4944 4945 short ssincos - tbl_trans # $35-0 fsincos norm 4946 short ssincosz - tbl_trans # $35-1 fsincos zero 4947 short ssincosi - tbl_trans # $35-2 fsincos inf 4948 short ssincosqnan - tbl_trans # $35-3 fsincos qnan 4949 short ssincosd - tbl_trans # $35-5 fsincos denorm 4950 short ssincossnan - tbl_trans # $35-4 fsincos snan 4951 short tbl_trans - tbl_trans # $35-6 fsincos unnorm 4952 short tbl_trans - tbl_trans # $35-7 ERROR 4953 4954 short ssincos - tbl_trans # $36-0 fsincos norm 4955 short ssincosz - tbl_trans # $36-1 fsincos zero 4956 short ssincosi - tbl_trans # $36-2 fsincos inf 4957 short ssincosqnan - tbl_trans # $36-3 fsincos qnan 4958 short ssincosd - tbl_trans # $36-5 fsincos denorm 4959 short ssincossnan - tbl_trans # $36-4 fsincos snan 4960 short tbl_trans - tbl_trans # $36-6 fsincos unnorm 4961 short tbl_trans - tbl_trans # $36-7 ERROR 4962 4963 short ssincos - tbl_trans # $37-0 fsincos norm 4964 short ssincosz - tbl_trans # $37-1 fsincos zero 4965 short ssincosi - tbl_trans # $37-2 fsincos inf 4966 short ssincosqnan - tbl_trans # $37-3 fsincos qnan 4967 short ssincosd - tbl_trans # $37-5 fsincos denorm 4968 short ssincossnan - tbl_trans # $37-4 fsincos snan 4969 short tbl_trans - tbl_trans # $37-6 fsincos unnorm 4970 short tbl_trans - tbl_trans # $37-7 ERROR 4971 4972########## 4973 4974# the instruction fetch access for the displacement word for the 4975# fdbcc emulation failed. here, we create an access error frame 4976# from the current frame and branch to _real_access(). 4977funimp_iacc: 4978 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 4979 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs 4980 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 4981 4982 mov.l USER_FPIAR(%a6),EXC_PC(%a6) # store current PC 4983 4984 unlk %a6 4985 4986 mov.l (%sp),-(%sp) # store SR,hi(PC) 4987 mov.w 0x8(%sp),0x4(%sp) # store lo(PC) 4988 mov.w &0x4008,0x6(%sp) # store voff 4989 mov.l 0x2(%sp),0x8(%sp) # store EA 4990 mov.l &0x09428001,0xc(%sp) # store FSLW 4991 4992 btst &0x5,(%sp) # user or supervisor mode? 4993 beq.b funimp_iacc_end # user 4994 bset &0x2,0xd(%sp) # set supervisor TM bit 4995 4996funimp_iacc_end: 4997 bra.l _real_access 4998 4999######################################################################### 5000# ssin(): computes the sine of a normalized input #
5001# ssind(): computes the sine of a denormalized input # 5002# scos(): computes the cosine of a normalized input # 5003# scosd(): computes the cosine of a denormalized input # 5004# ssincos(): computes the sine and cosine of a normalized input # 5005# ssincosd(): computes the sine and cosine of a denormalized input # 5006# # 5007# INPUT *************************************************************** # 5008# a0 = pointer to extended precision input # 5009# d0 = round precision,mode # 5010# # 5011# OUTPUT ************************************************************** # 5012# fp0 = sin(X) or cos(X) # 5013# # 5014# For ssincos(X): # 5015# fp0 = sin(X) # 5016# fp1 = cos(X) # 5017# # 5018# ACCURACY and MONOTONICITY ******************************************* # 5019# The returned result is within 1 ulp in 64 significant bit, i.e. # 5020# within 0.5001 ulp to 53 bits if the result is subsequently # 5021# rounded to double precision. The result is provably monotonic # 5022# in double precision. # 5023# # 5024# ALGORITHM *********************************************************** # 5025# # 5026# SIN and COS: # 5027# 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1. # 5028# # 5029# 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7. # 5030# # 5031# 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let # 5032# k = N mod 4, so in particular, k = 0,1,2,or 3. # 5033# Overwrite k by k := k + AdjN. # 5034# # 5035# 4. If k is even, go to 6. # 5036# # 5037# 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. # 5038# Return sgn*cos(r) where cos(r) is approximated by an # 5039# even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)), # 5040# s = r*r. # 5041# Exit. # 5042# # 5043# 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r) # 5044# where sin(r) is approximated by an odd polynomial in r # 5045# r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r. # 5046# Exit. # 5047# # 5048# 7. If |X| > 1, go to 9. # 5049# # 5050# 8. (|X|<2**(-40)) If SIN is invoked, return X; # 5051# otherwise return 1. # 5052# # 5053# 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, # 5054# go back to 3. # 5055# # 5056# SINCOS: # 5057# 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. # 5058# # 5059# 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let # 5060# k = N mod 4, so in particular, k = 0,1,2,or 3. # 5061# # 5062# 3. If k is even, go to 5. # 5063# # 5064# 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie. # 5065# j1 exclusive or with the l.s.b. of k. # 5066# sgn1 := (-1)**j1, sgn2 := (-1)**j2. # 5067# SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where # 5068# sin(r) and cos(r) are computed as odd and even # 5069# polynomials in r, respectively. Exit # 5070# # 5071# 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1. # 5072# SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where # 5073# sin(r) and cos(r) are computed as odd and even # 5074# polynomials in r, respectively. Exit # 5075# # 5076# 6. If |X| > 1, go to 8. # 5077# # 5078# 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit. # 5079# # 5080# 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, # 5081# go back to 2. # 5082# # 5083######################################################################### 5084 5085SINA7: long 0xBD6AAA77,0xCCC994F5 5086SINA6: long 0x3DE61209,0x7AAE8DA1 5087SINA5: long 0xBE5AE645,0x2A118AE4 5088SINA4: long 0x3EC71DE3,0xA5341531 5089SINA3: long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000 5090SINA2: long 0x3FF80000,0x88888888,0x888859AF,0x00000000 5091SINA1: long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000 5092 5093COSB8: long 0x3D2AC4D0,0xD6011EE3 5094COSB7: long 0xBDA9396F,0x9F45AC19 5095COSB6: long 0x3E21EED9,0x0612C972 5096COSB5: long 0xBE927E4F,0xB79D9FCF 5097COSB4: long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000 5098COSB3: long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000 5099COSB2: long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E 5100COSB1: long 0xBF000000 5101 5102 set INARG,FP_SCR0 5103 5104 set X,FP_SCR0 5105# set XDCARE,X+2 5106 set XFRAC,X+4 5107 5108 set RPRIME,FP_SCR0 5109 set SPRIME,FP_SCR1 5110 5111 set POSNEG1,L_SCR1 5112 set TWOTO63,L_SCR1 5113 5114 set ENDFLAG,L_SCR2 5115 set INT,L_SCR2 5116 5117 set ADJN,L_SCR3 5118 5119############################################ 5120 global ssin 5121ssin: 5122 mov.l &0,ADJN(%a6) # yes; SET ADJN TO 0 5123 bra.b SINBGN 5124 5125############################################ 5126 global scos 5127scos: 5128 mov.l &1,ADJN(%a6) # yes; SET ADJN TO 1 5129 5130############################################ 5131SINBGN: 5132#--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE 5133 5134 fmov.x (%a0),%fp0 # LOAD INPUT 5135 fmov.x %fp0,X(%a6) # save input at X 5136 5137# "COMPACTIFY" X 5138 mov.l (%a0),%d1 # put exp in hi word 5139 mov.w 4(%a0),%d1 # fetch hi(man) 5140 and.l &0x7FFFFFFF,%d1 # strip sign 5141 5142 cmpi.l %d1,&0x3FD78000 # is |X| >= 2**(-40)? 5143 bge.b SOK1 # no 5144 bra.w SINSM # yes; input is very small 5145 5146SOK1: 5147 cmp.l %d1,&0x4004BC7E # is |X| < 15 PI? 5148 blt.b SINMAIN # no 5149 bra.w SREDUCEX # yes; input is very large 5150 5151#--THIS IS THE USUAL CASE, |X| <= 15 PI. 5152#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP. 5153SINMAIN: 5154 fmov.x %fp0,%fp1 5155 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI 5156 5157 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32 5158 5159 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER 5160 5161 mov.l INT(%a6),%d1 # make a copy of N 5162 asl.l &4,%d1 # N *= 16 5163 add.l %d1,%a1 # tbl_addr = a1 + (N*16) 5164 5165# A1 IS THE ADDRESS OF N*PIBY2 5166# ...WHICH IS IN TWO PIECES Y1 & Y2 5167 fsub.x (%a1)+,%fp0 # X-Y1 5168 fsub.s (%a1),%fp0 # fp0 = R = (X-Y1)-Y2 5169 5170SINCONT: 5171#--continuation from REDUCEX 5172 5173#--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED 5174 mov.l INT(%a6),%d1 5175 add.l ADJN(%a6),%d1 # SEE IF D0 IS ODD OR EVEN 5176 ror.l &1,%d1 # D0 WAS ODD IFF D0 IS NEGATIVE 5177 cmp.l %d1,&0 5178 blt.w COSPOLY 5179 5180#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J. 5181#--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY 5182#--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE 5183#--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS 5184#--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))]) 5185#--WHERE T=S*S. 5186#--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION 5187#--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT. 5188SINPOLY: 5189 fmovm.x &0x0c,-(%sp) # save fp2/fp3 5190 5191 fmov.x %fp0,X(%a6) # X IS R 5192 fmul.x %fp0,%fp0 # FP0 IS S 5193 5194 fmov.d SINA7(%pc),%fp3 5195 fmov.d SINA6(%pc),%fp2 5196 5197 fmov.x %fp0,%fp1 5198 fmul.x %fp1,%fp1 # FP1 IS T 5199 5200 ror.l &1,%d1 5201 and.l &0x80000000,%d1 5202# ...LEAST SIG. BIT OF D0 IN SIGN POSITION 5203 eor.l %d1,X(%a6) # X IS NOW R'= SGN*R 5204 5205 fmul.x %fp1,%fp3 # TA7 5206 fmul.x %fp1,%fp2 # TA6 5207 5208 fadd.d SINA5(%pc),%fp3 # A5+TA7 5209 fadd.d SINA4(%pc),%fp2 # A4+TA6 5210 5211 fmul.x %fp1,%fp3 # T(A5+TA7) 5212 fmul.x %fp1,%fp2 # T(A4+TA6) 5213 5214 fadd.d SINA3(%pc),%fp3 # A3+T(A5+TA7) 5215 fadd.x SINA2(%pc),%fp2 # A2+T(A4+TA6) 5216 5217 fmul.x %fp3,%fp1 # T(A3+T(A5+TA7)) 5218 5219 fmul.x %fp0,%fp2 # S(A2+T(A4+TA6)) 5220 fadd.x SINA1(%pc),%fp1 # A1+T(A3+T(A5+TA7)) 5221 fmul.x X(%a6),%fp0 # R'*S 5222 5223 fadd.x %fp2,%fp1 # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] 5224 5225 fmul.x %fp1,%fp0 # SIN(R')-R' 5226 5227 fmovm.x (%sp)+,&0x30 # restore fp2/fp3 5228 5229 fmov.l %d0,%fpcr # restore users round mode,prec 5230 fadd.x X(%a6),%fp0 # last inst - possible exception set 5231 bra t_inx2 5232 5233#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J. 5234#--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY 5235#--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE 5236#--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS 5237#--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))]) 5238#--WHERE T=S*S. 5239#--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION