PageRenderTime 90ms CodeModel.GetById 25ms app.highlight 32ms RepoModel.GetById 2ms app.codeStats 3ms

/arch/m68k/ifpsp060/src/pfpsp.S

https://bitbucket.org/evzijst/gittest
Assembly | 14745 lines | 13552 code | 1193 blank | 0 comment | 323 complexity | 175cf69aa2f13a5f5a79a01ab9b41c33 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   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# freal.s:
  30#	This file is appended to the top of the 060FPSP package
  31# and contains the entry points into the package. The user, in
  32# effect, branches to one of the branch table entries located
  33# after _060FPSP_TABLE.
  34#	Also, subroutine stubs exist in this file (_fpsp_done for
  35# example) that are referenced by the FPSP package itself in order
  36# to call a given routine. The stub routine actually performs the
  37# callout. The FPSP code does a "bsr" to the stub routine. This
  38# extra layer of hierarchy adds a slight performance penalty but
  39# it makes the FPSP code easier to read and more mainatinable.
  40#
  41
  42set	_off_bsun,	0x00
  43set	_off_snan,	0x04
  44set	_off_operr,	0x08
  45set	_off_ovfl,	0x0c
  46set	_off_unfl,	0x10
  47set	_off_dz,	0x14
  48set	_off_inex,	0x18
  49set	_off_fline,	0x1c
  50set	_off_fpu_dis,	0x20
  51set	_off_trap,	0x24
  52set	_off_trace,	0x28
  53set	_off_access,	0x2c
  54set	_off_done,	0x30
  55
  56set	_off_imr,	0x40
  57set	_off_dmr,	0x44
  58set	_off_dmw,	0x48
  59set	_off_irw,	0x4c
  60set	_off_irl,	0x50
  61set	_off_drb,	0x54
  62set	_off_drw,	0x58
  63set	_off_drl,	0x5c
  64set	_off_dwb,	0x60
  65set	_off_dww,	0x64
  66set	_off_dwl,	0x68
  67
  68_060FPSP_TABLE:
  69
  70###############################################################
  71
  72# Here's the table of ENTRY POINTS for those linking the package.
  73	bra.l		_fpsp_snan
  74	short		0x0000
  75	bra.l		_fpsp_operr
  76	short		0x0000
  77	bra.l		_fpsp_ovfl
  78	short		0x0000
  79	bra.l		_fpsp_unfl
  80	short		0x0000
  81	bra.l		_fpsp_dz
  82	short		0x0000
  83	bra.l		_fpsp_inex
  84	short		0x0000
  85	bra.l		_fpsp_fline
  86	short		0x0000
  87	bra.l		_fpsp_unsupp
  88	short		0x0000
  89	bra.l		_fpsp_effadd
  90	short		0x0000
  91
  92	space		56
  93
  94###############################################################
  95	global		_fpsp_done
  96_fpsp_done:
  97	mov.l		%d0,-(%sp)
  98	mov.l		(_060FPSP_TABLE-0x80+_off_done,%pc),%d0
  99	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 100	mov.l		0x4(%sp),%d0
 101	rtd		&0x4
 102
 103	global		_real_ovfl
 104_real_ovfl:
 105	mov.l		%d0,-(%sp)
 106	mov.l		(_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
 107	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 108	mov.l		0x4(%sp),%d0
 109	rtd		&0x4
 110
 111	global		_real_unfl
 112_real_unfl:
 113	mov.l		%d0,-(%sp)
 114	mov.l		(_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
 115	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 116	mov.l		0x4(%sp),%d0
 117	rtd		&0x4
 118
 119	global		_real_inex
 120_real_inex:
 121	mov.l		%d0,-(%sp)
 122	mov.l		(_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
 123	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 124	mov.l		0x4(%sp),%d0
 125	rtd		&0x4
 126
 127	global		_real_bsun
 128_real_bsun:
 129	mov.l		%d0,-(%sp)
 130	mov.l		(_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
 131	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 132	mov.l		0x4(%sp),%d0
 133	rtd		&0x4
 134
 135	global		_real_operr
 136_real_operr:
 137	mov.l		%d0,-(%sp)
 138	mov.l		(_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
 139	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 140	mov.l		0x4(%sp),%d0
 141	rtd		&0x4
 142
 143	global		_real_snan
 144_real_snan:
 145	mov.l		%d0,-(%sp)
 146	mov.l		(_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
 147	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 148	mov.l		0x4(%sp),%d0
 149	rtd		&0x4
 150
 151	global		_real_dz
 152_real_dz:
 153	mov.l		%d0,-(%sp)
 154	mov.l		(_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
 155	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 156	mov.l		0x4(%sp),%d0
 157	rtd		&0x4
 158
 159	global		_real_fline
 160_real_fline:
 161	mov.l		%d0,-(%sp)
 162	mov.l		(_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
 163	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 164	mov.l		0x4(%sp),%d0
 165	rtd		&0x4
 166
 167	global		_real_fpu_disabled
 168_real_fpu_disabled:
 169	mov.l		%d0,-(%sp)
 170	mov.l		(_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
 171	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 172	mov.l		0x4(%sp),%d0
 173	rtd		&0x4
 174
 175	global		_real_trap
 176_real_trap:
 177	mov.l		%d0,-(%sp)
 178	mov.l		(_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
 179	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 180	mov.l		0x4(%sp),%d0
 181	rtd		&0x4
 182
 183	global		_real_trace
 184_real_trace:
 185	mov.l		%d0,-(%sp)
 186	mov.l		(_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
 187	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 188	mov.l		0x4(%sp),%d0
 189	rtd		&0x4
 190
 191	global		_real_access
 192_real_access:
 193	mov.l		%d0,-(%sp)
 194	mov.l		(_060FPSP_TABLE-0x80+_off_access,%pc),%d0
 195	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 196	mov.l		0x4(%sp),%d0
 197	rtd		&0x4
 198
 199#######################################
 200
 201	global		_imem_read
 202_imem_read:
 203	mov.l		%d0,-(%sp)
 204	mov.l		(_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
 205	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 206	mov.l		0x4(%sp),%d0
 207	rtd		&0x4
 208
 209	global		_dmem_read
 210_dmem_read:
 211	mov.l		%d0,-(%sp)
 212	mov.l		(_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
 213	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 214	mov.l		0x4(%sp),%d0
 215	rtd		&0x4
 216
 217	global		_dmem_write
 218_dmem_write:
 219	mov.l		%d0,-(%sp)
 220	mov.l		(_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
 221	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 222	mov.l		0x4(%sp),%d0
 223	rtd		&0x4
 224
 225	global		_imem_read_word
 226_imem_read_word:
 227	mov.l		%d0,-(%sp)
 228	mov.l		(_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
 229	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 230	mov.l		0x4(%sp),%d0
 231	rtd		&0x4
 232
 233	global		_imem_read_long
 234_imem_read_long:
 235	mov.l		%d0,-(%sp)
 236	mov.l		(_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
 237	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 238	mov.l		0x4(%sp),%d0
 239	rtd		&0x4
 240
 241	global		_dmem_read_byte
 242_dmem_read_byte:
 243	mov.l		%d0,-(%sp)
 244	mov.l		(_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
 245	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 246	mov.l		0x4(%sp),%d0
 247	rtd		&0x4
 248
 249	global		_dmem_read_word
 250_dmem_read_word:
 251	mov.l		%d0,-(%sp)
 252	mov.l		(_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
 253	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 254	mov.l		0x4(%sp),%d0
 255	rtd		&0x4
 256
 257	global		_dmem_read_long
 258_dmem_read_long:
 259	mov.l		%d0,-(%sp)
 260	mov.l		(_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
 261	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 262	mov.l		0x4(%sp),%d0
 263	rtd		&0x4
 264
 265	global		_dmem_write_byte
 266_dmem_write_byte:
 267	mov.l		%d0,-(%sp)
 268	mov.l		(_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
 269	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 270	mov.l		0x4(%sp),%d0
 271	rtd		&0x4
 272
 273	global		_dmem_write_word
 274_dmem_write_word:
 275	mov.l		%d0,-(%sp)
 276	mov.l		(_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
 277	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 278	mov.l		0x4(%sp),%d0
 279	rtd		&0x4
 280
 281	global		_dmem_write_long
 282_dmem_write_long:
 283	mov.l		%d0,-(%sp)
 284	mov.l		(_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
 285	pea.l		(_060FPSP_TABLE-0x80,%pc,%d0)
 286	mov.l		0x4(%sp),%d0
 287	rtd		&0x4
 288
 289#
 290# This file contains a set of define statements for constants
 291# in order to promote readability within the corecode itself.
 292#
 293
 294set LOCAL_SIZE,		192			# stack frame size(bytes)
 295set LV,			-LOCAL_SIZE		# stack offset
 296
 297set EXC_SR,		0x4			# stack status register
 298set EXC_PC,		0x6			# stack pc
 299set EXC_VOFF,		0xa			# stacked vector offset
 300set EXC_EA,		0xc			# stacked <ea>
 301
 302set EXC_FP,		0x0			# frame pointer
 303
 304set EXC_AREGS,		-68			# offset of all address regs
 305set EXC_DREGS,		-100			# offset of all data regs
 306set EXC_FPREGS,		-36			# offset of all fp regs
 307
 308set EXC_A7,		EXC_AREGS+(7*4)		# offset of saved a7
 309set OLD_A7,		EXC_AREGS+(6*4)		# extra copy of saved a7
 310set EXC_A6,		EXC_AREGS+(6*4)		# offset of saved a6
 311set EXC_A5,		EXC_AREGS+(5*4)
 312set EXC_A4,		EXC_AREGS+(4*4)
 313set EXC_A3,		EXC_AREGS+(3*4)
 314set EXC_A2,		EXC_AREGS+(2*4)
 315set EXC_A1,		EXC_AREGS+(1*4)
 316set EXC_A0,		EXC_AREGS+(0*4)
 317set EXC_D7,		EXC_DREGS+(7*4)
 318set EXC_D6,		EXC_DREGS+(6*4)
 319set EXC_D5,		EXC_DREGS+(5*4)
 320set EXC_D4,		EXC_DREGS+(4*4)
 321set EXC_D3,		EXC_DREGS+(3*4)
 322set EXC_D2,		EXC_DREGS+(2*4)
 323set EXC_D1,		EXC_DREGS+(1*4)
 324set EXC_D0,		EXC_DREGS+(0*4)
 325
 326set EXC_FP0,		EXC_FPREGS+(0*12)	# offset of saved fp0
 327set EXC_FP1,		EXC_FPREGS+(1*12)	# offset of saved fp1
 328set EXC_FP2,		EXC_FPREGS+(2*12)	# offset of saved fp2 (not used)
 329
 330set FP_SCR1,		LV+80			# fp scratch 1
 331set FP_SCR1_EX,		FP_SCR1+0
 332set FP_SCR1_SGN,	FP_SCR1+2
 333set FP_SCR1_HI,		FP_SCR1+4
 334set FP_SCR1_LO,		FP_SCR1+8
 335
 336set FP_SCR0,		LV+68			# fp scratch 0
 337set FP_SCR0_EX,		FP_SCR0+0
 338set FP_SCR0_SGN,	FP_SCR0+2
 339set FP_SCR0_HI,		FP_SCR0+4
 340set FP_SCR0_LO,		FP_SCR0+8
 341
 342set FP_DST,		LV+56			# fp destination operand
 343set FP_DST_EX,		FP_DST+0
 344set FP_DST_SGN,		FP_DST+2
 345set FP_DST_HI,		FP_DST+4
 346set FP_DST_LO,		FP_DST+8
 347
 348set FP_SRC,		LV+44			# fp source operand
 349set FP_SRC_EX,		FP_SRC+0
 350set FP_SRC_SGN,		FP_SRC+2
 351set FP_SRC_HI,		FP_SRC+4
 352set FP_SRC_LO,		FP_SRC+8
 353
 354set USER_FPIAR,		LV+40			# FP instr address register
 355
 356set USER_FPSR,		LV+36			# FP status register
 357set FPSR_CC,		USER_FPSR+0		# FPSR condition codes
 358set FPSR_QBYTE,		USER_FPSR+1		# FPSR qoutient byte
 359set FPSR_EXCEPT,	USER_FPSR+2		# FPSR exception status byte
 360set FPSR_AEXCEPT,	USER_FPSR+3		# FPSR accrued exception byte
 361
 362set USER_FPCR,		LV+32			# FP control register
 363set FPCR_ENABLE,	USER_FPCR+2		# FPCR exception enable
 364set FPCR_MODE,		USER_FPCR+3		# FPCR rounding mode control
 365
 366set L_SCR3,		LV+28			# integer scratch 3
 367set L_SCR2,		LV+24			# integer scratch 2
 368set L_SCR1,		LV+20			# integer scratch 1
 369
 370set STORE_FLG,		LV+19			# flag: operand store (ie. not fcmp/ftst)
 371
 372set EXC_TEMP2,		LV+24			# temporary space
 373set EXC_TEMP,		LV+16			# temporary space
 374
 375set DTAG,		LV+15			# destination operand type
 376set STAG,		LV+14			# source operand type
 377
 378set SPCOND_FLG,		LV+10			# flag: special case (see below)
 379
 380set EXC_CC,		LV+8			# saved condition codes
 381set EXC_EXTWPTR,	LV+4			# saved current PC (active)
 382set EXC_EXTWORD,	LV+2			# saved extension word
 383set EXC_CMDREG,		LV+2			# saved extension word
 384set EXC_OPWORD,		LV+0			# saved operation word
 385
 386################################
 387
 388# Helpful macros
 389
 390set FTEMP,		0			# offsets within an
 391set FTEMP_EX,		0			# extended precision
 392set FTEMP_SGN,		2			# value saved in memory.
 393set FTEMP_HI,		4
 394set FTEMP_LO,		8
 395set FTEMP_GRS,		12
 396
 397set LOCAL,		0			# offsets within an
 398set LOCAL_EX,		0			# extended precision
 399set LOCAL_SGN,		2			# value saved in memory.
 400set LOCAL_HI,		4
 401set LOCAL_LO,		8
 402set LOCAL_GRS,		12
 403
 404set DST,		0			# offsets within an
 405set DST_EX,		0			# extended precision
 406set DST_HI,		4			# value saved in memory.
 407set DST_LO,		8
 408
 409set SRC,		0			# offsets within an
 410set SRC_EX,		0			# extended precision
 411set SRC_HI,		4			# value saved in memory.
 412set SRC_LO,		8
 413
 414set SGL_LO,		0x3f81			# min sgl prec exponent
 415set SGL_HI,		0x407e			# max sgl prec exponent
 416set DBL_LO,		0x3c01			# min dbl prec exponent
 417set DBL_HI,		0x43fe			# max dbl prec exponent
 418set EXT_LO,		0x0			# min ext prec exponent
 419set EXT_HI,		0x7ffe			# max ext prec exponent
 420
 421set EXT_BIAS,		0x3fff			# extended precision bias
 422set SGL_BIAS,		0x007f			# single precision bias
 423set DBL_BIAS,		0x03ff			# double precision bias
 424
 425set NORM,		0x00			# operand type for STAG/DTAG
 426set ZERO,		0x01			# operand type for STAG/DTAG
 427set INF,		0x02			# operand type for STAG/DTAG
 428set QNAN,		0x03			# operand type for STAG/DTAG
 429set DENORM,		0x04			# operand type for STAG/DTAG
 430set SNAN,		0x05			# operand type for STAG/DTAG
 431set UNNORM,		0x06			# operand type for STAG/DTAG
 432
 433##################
 434# FPSR/FPCR bits #
 435##################
 436set neg_bit,		0x3			# negative result
 437set z_bit,		0x2			# zero result
 438set inf_bit,		0x1			# infinite result
 439set nan_bit,		0x0			# NAN result
 440
 441set q_sn_bit,		0x7			# sign bit of quotient byte
 442
 443set bsun_bit,		7			# branch on unordered
 444set snan_bit,		6			# signalling NAN
 445set operr_bit,		5			# operand error
 446set ovfl_bit,		4			# overflow
 447set unfl_bit,		3			# underflow
 448set dz_bit,		2			# divide by zero
 449set inex2_bit,		1			# inexact result 2
 450set inex1_bit,		0			# inexact result 1
 451
 452set aiop_bit,		7			# accrued inexact operation bit
 453set aovfl_bit,		6			# accrued overflow bit
 454set aunfl_bit,		5			# accrued underflow bit
 455set adz_bit,		4			# accrued dz bit
 456set ainex_bit,		3			# accrued inexact bit
 457
 458#############################
 459# FPSR individual bit masks #
 460#############################
 461set neg_mask,		0x08000000		# negative bit mask (lw)
 462set inf_mask,		0x02000000		# infinity bit mask (lw)
 463set z_mask,		0x04000000		# zero bit mask (lw)
 464set nan_mask,		0x01000000		# nan bit mask (lw)
 465
 466set neg_bmask,		0x08			# negative bit mask (byte)
 467set inf_bmask,		0x02			# infinity bit mask (byte)
 468set z_bmask,		0x04			# zero bit mask (byte)
 469set nan_bmask,		0x01			# nan bit mask (byte)
 470
 471set bsun_mask,		0x00008000		# bsun exception mask
 472set snan_mask,		0x00004000		# snan exception mask
 473set operr_mask,		0x00002000		# operr exception mask
 474set ovfl_mask,		0x00001000		# overflow exception mask
 475set unfl_mask,		0x00000800		# underflow exception mask
 476set dz_mask,		0x00000400		# dz exception mask
 477set inex2_mask,		0x00000200		# inex2 exception mask
 478set inex1_mask,		0x00000100		# inex1 exception mask
 479
 480set aiop_mask,		0x00000080		# accrued illegal operation
 481set aovfl_mask,		0x00000040		# accrued overflow
 482set aunfl_mask,		0x00000020		# accrued underflow
 483set adz_mask,		0x00000010		# accrued divide by zero
 484set ainex_mask,		0x00000008		# accrued inexact
 485
 486######################################
 487# FPSR combinations used in the FPSP #
 488######################################
 489set dzinf_mask,		inf_mask+dz_mask+adz_mask
 490set opnan_mask,		nan_mask+operr_mask+aiop_mask
 491set nzi_mask,		0x01ffffff		#clears N, Z, and I
 492set unfinx_mask,	unfl_mask+inex2_mask+aunfl_mask+ainex_mask
 493set unf2inx_mask,	unfl_mask+inex2_mask+ainex_mask
 494set ovfinx_mask,	ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
 495set inx1a_mask,		inex1_mask+ainex_mask
 496set inx2a_mask,		inex2_mask+ainex_mask
 497set snaniop_mask,	nan_mask+snan_mask+aiop_mask
 498set snaniop2_mask,	snan_mask+aiop_mask
 499set naniop_mask,	nan_mask+aiop_mask
 500set neginf_mask,	neg_mask+inf_mask
 501set infaiop_mask,	inf_mask+aiop_mask
 502set negz_mask,		neg_mask+z_mask
 503set opaop_mask,		operr_mask+aiop_mask
 504set unfl_inx_mask,	unfl_mask+aunfl_mask+ainex_mask
 505set ovfl_inx_mask,	ovfl_mask+aovfl_mask+ainex_mask
 506
 507#########
 508# misc. #
 509#########
 510set rnd_stky_bit,	29			# stky bit pos in longword
 511
 512set sign_bit,		0x7			# sign bit
 513set signan_bit,		0x6			# signalling nan bit
 514
 515set sgl_thresh,		0x3f81			# minimum sgl exponent
 516set dbl_thresh,		0x3c01			# minimum dbl exponent
 517
 518set x_mode,		0x0			# extended precision
 519set s_mode,		0x4			# single precision
 520set d_mode,		0x8			# double precision
 521
 522set rn_mode,		0x0			# round-to-nearest
 523set rz_mode,		0x1			# round-to-zero
 524set rm_mode,		0x2			# round-tp-minus-infinity
 525set rp_mode,		0x3			# round-to-plus-infinity
 526
 527set mantissalen,	64			# length of mantissa in bits
 528
 529set BYTE,		1			# len(byte) == 1 byte
 530set WORD,		2			# len(word) == 2 bytes
 531set LONG,		4			# len(longword) == 2 bytes
 532
 533set BSUN_VEC,		0xc0			# bsun    vector offset
 534set INEX_VEC,		0xc4			# inexact vector offset
 535set DZ_VEC,		0xc8			# dz      vector offset
 536set UNFL_VEC,		0xcc			# unfl    vector offset
 537set OPERR_VEC,		0xd0			# operr   vector offset
 538set OVFL_VEC,		0xd4			# ovfl    vector offset
 539set SNAN_VEC,		0xd8			# snan    vector offset
 540
 541###########################
 542# SPecial CONDition FLaGs #
 543###########################
 544set ftrapcc_flg,	0x01			# flag bit: ftrapcc exception
 545set fbsun_flg,		0x02			# flag bit: bsun exception
 546set mia7_flg,		0x04			# flag bit: (a7)+ <ea>
 547set mda7_flg,		0x08			# flag bit: -(a7) <ea>
 548set fmovm_flg,		0x40			# flag bit: fmovm instruction
 549set immed_flg,		0x80			# flag bit: &<data> <ea>
 550
 551set ftrapcc_bit,	0x0
 552set fbsun_bit,		0x1
 553set mia7_bit,		0x2
 554set mda7_bit,		0x3
 555set immed_bit,		0x7
 556
 557##################################
 558# TRANSCENDENTAL "LAST-OP" FLAGS #
 559##################################
 560set FMUL_OP,		0x0			# fmul instr performed last
 561set FDIV_OP,		0x1			# fdiv performed last
 562set FADD_OP,		0x2			# fadd performed last
 563set FMOV_OP,		0x3			# fmov performed last
 564
 565#############
 566# CONSTANTS #
 567#############
 568T1:	long		0x40C62D38,0xD3D64634	# 16381 LOG2 LEAD
 569T2:	long		0x3D6F90AE,0xB1E75CC7	# 16381 LOG2 TRAIL
 570
 571PI:	long		0x40000000,0xC90FDAA2,0x2168C235,0x00000000
 572PIBY2:	long		0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
 573
 574TWOBYPI:
 575	long		0x3FE45F30,0x6DC9C883
 576
 577#########################################################################
 578# XDEF ****************************************************************	#
 579#	_fpsp_ovfl(): 060FPSP entry point for FP Overflow exception.	#
 580#									#
 581#	This handler should be the first code executed upon taking the	#
 582#	FP Overflow exception in an operating system.			#
 583#									#
 584# XREF ****************************************************************	#
 585#	_imem_read_long() - read instruction longword			#
 586#	fix_skewed_ops() - adjust src operand in fsave frame		#
 587#	set_tag_x() - determine optype of src/dst operands		#
 588#	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
 589#	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
 590#	load_fpn2() - load dst operand from FP regfile			#
 591#	fout() - emulate an opclass 3 instruction			#
 592#	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
 593#	_fpsp_done() - "callout" for 060FPSP exit (all work done!)	#
 594#	_real_ovfl() - "callout" for Overflow exception enabled code	#
 595#	_real_inex() - "callout" for Inexact exception enabled code	#
 596#	_real_trace() - "callout" for Trace exception code		#
 597#									#
 598# INPUT ***************************************************************	#
 599#	- The system stack contains the FP Ovfl exception stack frame	#
 600#	- The fsave frame contains the source operand			#
 601#									#
 602# OUTPUT **************************************************************	#
 603#	Overflow Exception enabled:					#
 604#	- The system stack is unchanged					#
 605#	- The fsave frame contains the adjusted src op for opclass 0,2	#
 606#	Overflow Exception disabled:					#
 607#	- The system stack is unchanged					#
 608#	- The "exception present" flag in the fsave frame is cleared	#
 609#									#
 610# ALGORITHM ***********************************************************	#
 611#	On the 060, if an FP overflow is present as the result of any	#
 612# instruction, the 060 will take an overflow exception whether the	#
 613# exception is enabled or disabled in the FPCR. For the disabled case,	#
 614# This handler emulates the instruction to determine what the correct	#
 615# default result should be for the operation. This default result is	#
 616# then stored in either the FP regfile, data regfile, or memory.	#
 617# Finally, the handler exits through the "callout" _fpsp_done()		#
 618# denoting that no exceptional conditions exist within the machine.	#
 619#	If the exception is enabled, then this handler must create the	#
 620# exceptional operand and plave it in the fsave state frame, and store	#
 621# the default result (only if the instruction is opclass 3). For	#
 622# exceptions enabled, this handler must exit through the "callout"	#
 623# _real_ovfl() so that the operating system enabled overflow handler	#
 624# can handle this case.							#
 625#	Two other conditions exist. First, if overflow was disabled	#
 626# but the inexact exception was enabled, this handler must exit		#
 627# through the "callout" _real_inex() regardless of whether the result	#
 628# was inexact.								#
 629#	Also, in the case of an opclass three instruction where		#
 630# overflow was disabled and the trace exception was enabled, this	#
 631# handler must exit through the "callout" _real_trace().		#
 632#									#
 633#########################################################################
 634
 635	global		_fpsp_ovfl
 636_fpsp_ovfl:
 637
 638#$#	sub.l		&24,%sp			# make room for src/dst
 639
 640	link.w		%a6,&-LOCAL_SIZE	# init stack frame
 641
 642	fsave		FP_SRC(%a6)		# grab the "busy" frame
 643
 644	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
 645	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
 646	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
 647
 648# the FPIAR holds the "current PC" of the faulting instruction
 649	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
 650	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
 651	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
 652	bsr.l		_imem_read_long		# fetch the instruction words
 653	mov.l		%d0,EXC_OPWORD(%a6)
 654
 655##############################################################################
 656
 657	btst		&0x5,EXC_CMDREG(%a6)	# is instr an fmove out?
 658	bne.w		fovfl_out
 659
 660
 661	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
 662	bsr.l		fix_skewed_ops		# fix src op
 663
 664# since, I believe, only NORMs and DENORMs can come through here,
 665# maybe we can avoid the subroutine call.
 666	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
 667	bsr.l		set_tag_x		# tag the operand type
 668	mov.b		%d0,STAG(%a6)		# maybe NORM,DENORM
 669
 670# bit five of the fp extension word separates the monadic and dyadic operations
 671# that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
 672# will never take this exception.
 673	btst		&0x5,1+EXC_CMDREG(%a6)	# is operation monadic or dyadic?
 674	beq.b		fovfl_extract		# monadic
 675
 676	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
 677	bsr.l		load_fpn2		# load dst into FP_DST
 678
 679	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
 680	bsr.l		set_tag_x		# tag the operand type
 681	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
 682	bne.b		fovfl_op2_done		# no
 683	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
 684fovfl_op2_done:
 685	mov.b		%d0,DTAG(%a6)		# save dst optype tag
 686
 687fovfl_extract:
 688
 689#$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
 690#$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
 691#$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
 692#$#	mov.l		FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
 693#$#	mov.l		FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
 694#$#	mov.l		FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
 695
 696	clr.l		%d0
 697	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
 698
 699	mov.b		1+EXC_CMDREG(%a6),%d1
 700	andi.w		&0x007f,%d1		# extract extension
 701
 702	andi.l		&0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
 703
 704	fmov.l		&0x0,%fpcr		# zero current control regs
 705	fmov.l		&0x0,%fpsr
 706
 707	lea		FP_SRC(%a6),%a0
 708	lea		FP_DST(%a6),%a1
 709
 710# maybe we can make these entry points ONLY the OVFL entry points of each routine.
 711	mov.l		(tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
 712	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
 713
 714# the operation has been emulated. the result is in fp0.
 715# the EXOP, if an exception occurred, is in fp1.
 716# we must save the default result regardless of whether
 717# traps are enabled or disabled.
 718	bfextu		EXC_CMDREG(%a6){&6:&3},%d0
 719	bsr.l		store_fpreg
 720
 721# the exceptional possibilities we have left ourselves with are ONLY overflow
 722# and inexact. and, the inexact is such that overflow occurred and was disabled
 723# but inexact was enabled.
 724	btst		&ovfl_bit,FPCR_ENABLE(%a6)
 725	bne.b		fovfl_ovfl_on
 726
 727	btst		&inex2_bit,FPCR_ENABLE(%a6)
 728	bne.b		fovfl_inex_on
 729
 730	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
 731	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
 732	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
 733
 734	unlk		%a6
 735#$#	add.l		&24,%sp
 736	bra.l		_fpsp_done
 737
 738# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
 739# in fp1. now, simply jump to _real_ovfl()!
 740fovfl_ovfl_on:
 741	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP (fp1) to stack
 742
 743	mov.w		&0xe005,2+FP_SRC(%a6)	# save exc status
 744
 745	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
 746	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
 747	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
 748
 749	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
 750
 751	unlk		%a6
 752
 753	bra.l		_real_ovfl
 754
 755# overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
 756# we must jump to real_inex().
 757fovfl_inex_on:
 758
 759	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP (fp1) to stack
 760
 761	mov.b		&0xc4,1+EXC_VOFF(%a6)	# vector offset = 0xc4
 762	mov.w		&0xe001,2+FP_SRC(%a6)	# save exc status
 763
 764	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
 765	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
 766	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
 767
 768	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
 769
 770	unlk		%a6
 771
 772	bra.l		_real_inex
 773
 774########################################################################
 775fovfl_out:
 776
 777
 778#$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
 779#$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
 780#$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
 781
 782# the src operand is definitely a NORM(!), so tag it as such
 783	mov.b		&NORM,STAG(%a6)		# set src optype tag
 784
 785	clr.l		%d0
 786	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
 787
 788	and.l		&0xffff00ff,USER_FPSR(%a6) # zero all but accured field
 789
 790	fmov.l		&0x0,%fpcr		# zero current control regs
 791	fmov.l		&0x0,%fpsr
 792
 793	lea		FP_SRC(%a6),%a0		# pass ptr to src operand
 794
 795	bsr.l		fout
 796
 797	btst		&ovfl_bit,FPCR_ENABLE(%a6)
 798	bne.w		fovfl_ovfl_on
 799
 800	btst		&inex2_bit,FPCR_ENABLE(%a6)
 801	bne.w		fovfl_inex_on
 802
 803	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
 804	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
 805	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
 806
 807	unlk		%a6
 808#$#	add.l		&24,%sp
 809
 810	btst		&0x7,(%sp)		# is trace on?
 811	beq.l		_fpsp_done		# no
 812
 813	fmov.l		%fpiar,0x8(%sp)		# "Current PC" is in FPIAR
 814	mov.w		&0x2024,0x6(%sp)	# stk fmt = 0x2; voff = 0x024
 815	bra.l		_real_trace
 816
 817#########################################################################
 818# XDEF ****************************************************************	#
 819#	_fpsp_unfl(): 060FPSP entry point for FP Underflow exception.	#
 820#									#
 821#	This handler should be the first code executed upon taking the	#
 822#	FP Underflow exception in an operating system.			#
 823#									#
 824# XREF ****************************************************************	#
 825#	_imem_read_long() - read instruction longword			#
 826#	fix_skewed_ops() - adjust src operand in fsave frame		#
 827#	set_tag_x() - determine optype of src/dst operands		#
 828#	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
 829#	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
 830#	load_fpn2() - load dst operand from FP regfile			#
 831#	fout() - emulate an opclass 3 instruction			#
 832#	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
 833#	_fpsp_done() - "callout" for 060FPSP exit (all work done!)	#
 834#	_real_ovfl() - "callout" for Overflow exception enabled code	#
 835#	_real_inex() - "callout" for Inexact exception enabled code	#
 836#	_real_trace() - "callout" for Trace exception code		#
 837#									#
 838# INPUT ***************************************************************	#
 839#	- The system stack contains the FP Unfl exception stack frame	#
 840#	- The fsave frame contains the source operand			#
 841#									#
 842# OUTPUT **************************************************************	#
 843#	Underflow Exception enabled:					#
 844#	- The system stack is unchanged					#
 845#	- The fsave frame contains the adjusted src op for opclass 0,2	#
 846#	Underflow Exception disabled:					#
 847#	- The system stack is unchanged					#
 848#	- The "exception present" flag in the fsave frame is cleared	#
 849#									#
 850# ALGORITHM ***********************************************************	#
 851#	On the 060, if an FP underflow is present as the result of any	#
 852# instruction, the 060 will take an underflow exception whether the	#
 853# exception is enabled or disabled in the FPCR. For the disabled case,	#
 854# This handler emulates the instruction to determine what the correct	#
 855# default result should be for the operation. This default result is	#
 856# then stored in either the FP regfile, data regfile, or memory.	#
 857# Finally, the handler exits through the "callout" _fpsp_done()		#
 858# denoting that no exceptional conditions exist within the machine.	#
 859#	If the exception is enabled, then this handler must create the	#
 860# exceptional operand and plave it in the fsave state frame, and store	#
 861# the default result (only if the instruction is opclass 3). For	#
 862# exceptions enabled, this handler must exit through the "callout"	#
 863# _real_unfl() so that the operating system enabled overflow handler	#
 864# can handle this case.							#
 865#	Two other conditions exist. First, if underflow was disabled	#
 866# but the inexact exception was enabled and the result was inexact,	#
 867# this handler must exit through the "callout" _real_inex().		#
 868# was inexact.								#
 869#	Also, in the case of an opclass three instruction where		#
 870# underflow was disabled and the trace exception was enabled, this	#
 871# handler must exit through the "callout" _real_trace().		#
 872#									#
 873#########################################################################
 874
 875	global		_fpsp_unfl
 876_fpsp_unfl:
 877
 878#$#	sub.l		&24,%sp			# make room for src/dst
 879
 880	link.w		%a6,&-LOCAL_SIZE	# init stack frame
 881
 882	fsave		FP_SRC(%a6)		# grab the "busy" frame
 883
 884	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
 885	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
 886	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
 887
 888# the FPIAR holds the "current PC" of the faulting instruction
 889	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
 890	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
 891	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
 892	bsr.l		_imem_read_long		# fetch the instruction words
 893	mov.l		%d0,EXC_OPWORD(%a6)
 894
 895##############################################################################
 896
 897	btst		&0x5,EXC_CMDREG(%a6)	# is instr an fmove out?
 898	bne.w		funfl_out
 899
 900
 901	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
 902	bsr.l		fix_skewed_ops		# fix src op
 903
 904	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
 905	bsr.l		set_tag_x		# tag the operand type
 906	mov.b		%d0,STAG(%a6)		# maybe NORM,DENORM
 907
 908# bit five of the fp ext word separates the monadic and dyadic operations
 909# that can pass through fpsp_unfl(). remember that fcmp, and ftst
 910# will never take this exception.
 911	btst		&0x5,1+EXC_CMDREG(%a6)	# is op monadic or dyadic?
 912	beq.b		funfl_extract		# monadic
 913
 914# now, what's left that's not dyadic is fsincos. we can distinguish it
 915# from all dyadics by the '0110xxx pattern
 916	btst		&0x4,1+EXC_CMDREG(%a6)	# is op an fsincos?
 917	bne.b		funfl_extract		# yes
 918
 919	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
 920	bsr.l		load_fpn2		# load dst into FP_DST
 921
 922	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
 923	bsr.l		set_tag_x		# tag the operand type
 924	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
 925	bne.b		funfl_op2_done		# no
 926	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
 927funfl_op2_done:
 928	mov.b		%d0,DTAG(%a6)		# save dst optype tag
 929
 930funfl_extract:
 931
 932#$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
 933#$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
 934#$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
 935#$#	mov.l		FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
 936#$#	mov.l		FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
 937#$#	mov.l		FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
 938
 939	clr.l		%d0
 940	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
 941
 942	mov.b		1+EXC_CMDREG(%a6),%d1
 943	andi.w		&0x007f,%d1		# extract extension
 944
 945	andi.l		&0x00ff01ff,USER_FPSR(%a6)
 946
 947	fmov.l		&0x0,%fpcr		# zero current control regs
 948	fmov.l		&0x0,%fpsr
 949
 950	lea		FP_SRC(%a6),%a0
 951	lea		FP_DST(%a6),%a1
 952
 953# maybe we can make these entry points ONLY the OVFL entry points of each routine.
 954	mov.l		(tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
 955	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
 956
 957	bfextu		EXC_CMDREG(%a6){&6:&3},%d0
 958	bsr.l		store_fpreg
 959
 960# The `060 FPU multiplier hardware is such that if the result of a
 961# multiply operation is the smallest possible normalized number
 962# (0x00000000_80000000_00000000), then the machine will take an
 963# underflow exception. Since this is incorrect, we need to check
 964# if our emulation, after re-doing the operation, decided that
 965# no underflow was called for. We do these checks only in
 966# funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
 967# special case will simply exit gracefully with the correct result.
 968
 969# the exceptional possibilities we have left ourselves with are ONLY overflow
 970# and inexact. and, the inexact is such that overflow occurred and was disabled
 971# but inexact was enabled.
 972	btst		&unfl_bit,FPCR_ENABLE(%a6)
 973	bne.b		funfl_unfl_on
 974
 975funfl_chkinex:
 976	btst		&inex2_bit,FPCR_ENABLE(%a6)
 977	bne.b		funfl_inex_on
 978
 979funfl_exit:
 980	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
 981	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
 982	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
 983
 984	unlk		%a6
 985#$#	add.l		&24,%sp
 986	bra.l		_fpsp_done
 987
 988# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
 989# in fp1 (don't forget to save fp0). what to do now?
 990# well, we simply have to get to go to _real_unfl()!
 991funfl_unfl_on:
 992
 993# The `060 FPU multiplier hardware is such that if the result of a
 994# multiply operation is the smallest possible normalized number
 995# (0x00000000_80000000_00000000), then the machine will take an
 996# underflow exception. Since this is incorrect, we check here to see
 997# if our emulation, after re-doing the operation, decided that
 998# no underflow was called for.
 999	btst		&unfl_bit,FPSR_EXCEPT(%a6)
1000	beq.w		funfl_chkinex
1001
1002funfl_unfl_on2:
1003	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP (fp1) to stack
1004
1005	mov.w		&0xe003,2+FP_SRC(%a6)	# save exc status
1006
1007	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
1008	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1009	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1010
1011	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
1012
1013	unlk		%a6
1014
1015	bra.l		_real_unfl
1016
1017# undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
1018# we must jump to real_inex().
1019funfl_inex_on:
1020
1021# The `060 FPU multiplier hardware is such that if the result of a
1022# multiply operation is the smallest possible normalized number
1023# (0x00000000_80000000_00000000), then the machine will take an
1024# underflow exception.
1025# But, whether bogus or not, if inexact is enabled AND it occurred,
1026# then we have to branch to real_inex.
1027
1028	btst		&inex2_bit,FPSR_EXCEPT(%a6)
1029	beq.w		funfl_exit
1030
1031funfl_inex_on2:
1032
1033	fmovm.x		&0x40,FP_SRC(%a6)	# save EXOP to stack
1034
1035	mov.b		&0xc4,1+EXC_VOFF(%a6)	# vector offset = 0xc4
1036	mov.w		&0xe001,2+FP_SRC(%a6)	# save exc status
1037
1038	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
1039	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1040	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1041
1042	frestore	FP_SRC(%a6)		# do this after fmovm,other f<op>s!
1043
1044	unlk		%a6
1045
1046	bra.l		_real_inex
1047
1048#######################################################################
1049funfl_out:
1050
1051
1052#$#	mov.l		FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
1053#$#	mov.l		FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
1054#$#	mov.l		FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
1055
1056# the src operand is definitely a NORM(!), so tag it as such
1057	mov.b		&NORM,STAG(%a6)		# set src optype tag
1058
1059	clr.l		%d0
1060	mov.b		FPCR_MODE(%a6),%d0	# pass rnd prec/mode
1061
1062	and.l		&0xffff00ff,USER_FPSR(%a6) # zero all but accured field
1063
1064	fmov.l		&0x0,%fpcr		# zero current control regs
1065	fmov.l		&0x0,%fpsr
1066
1067	lea		FP_SRC(%a6),%a0		# pass ptr to src operand
1068
1069	bsr.l		fout
1070
1071	btst		&unfl_bit,FPCR_ENABLE(%a6)
1072	bne.w		funfl_unfl_on2
1073
1074	btst		&inex2_bit,FPCR_ENABLE(%a6)
1075	bne.w		funfl_inex_on2
1076
1077	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0-fp1
1078	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1079	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1080
1081	unlk		%a6
1082#$#	add.l		&24,%sp
1083
1084	btst		&0x7,(%sp)		# is trace on?
1085	beq.l		_fpsp_done		# no
1086
1087	fmov.l		%fpiar,0x8(%sp)		# "Current PC" is in FPIAR
1088	mov.w		&0x2024,0x6(%sp)	# stk fmt = 0x2; voff = 0x024
1089	bra.l		_real_trace
1090
1091#########################################################################
1092# XDEF ****************************************************************	#
1093#	_fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented	#
1094#		        Data Type" exception.				#
1095#									#
1096#	This handler should be the first code executed upon taking the	#
1097#	FP Unimplemented Data Type exception in an operating system.	#
1098#									#
1099# XREF ****************************************************************	#
1100#	_imem_read_{word,long}() - read instruction word/longword	#
1101#	fix_skewed_ops() - adjust src operand in fsave frame		#
1102#	set_tag_x() - determine optype of src/dst operands		#
1103#	store_fpreg() - store opclass 0 or 2 result to FP regfile	#
1104#	unnorm_fix() - change UNNORM operands to NORM or ZERO		#
1105#	load_fpn2() - load dst operand from FP regfile			#
1106#	load_fpn1() - load src operand from FP regfile			#
1107#	fout() - emulate an opclass 3 instruction			#
1108#	tbl_unsupp - add of table of emulation routines for opclass 0,2	#
1109#	_real_inex() - "callout" to operating system inexact handler	#
1110#	_fpsp_done() - "callout" for exit; work all done		#
1111#	_real_trace() - "callout" for Trace enabled exception		#
1112#	funimp_skew() - adjust fsave src ops to "incorrect" value	#
1113#	_real_snan() - "callout" for SNAN exception			#
1114#	_real_operr() - "callout" for OPERR exception			#
1115#	_real_ovfl() - "callout" for OVFL exception			#
1116#	_real_unfl() - "callout" for UNFL exception			#
1117#	get_packed() - fetch packed operand from memory			#
1118#									#
1119# INPUT ***************************************************************	#
1120#	- The system stack contains the "Unimp Data Type" stk frame	#
1121#	- The fsave frame contains the ssrc op (for UNNORM/DENORM)	#
1122#									#
1123# OUTPUT **************************************************************	#
1124#	If Inexact exception (opclass 3):				#
1125#	- The system stack is changed to an Inexact exception stk frame	#
1126#	If SNAN exception (opclass 3):					#
1127#	- The system stack is changed to an SNAN exception stk frame	#
1128#	If OPERR exception (opclass 3):					#
1129#	- The system stack is changed to an OPERR exception stk frame	#
1130#	If OVFL exception (opclass 3):					#
1131#	- The system stack is changed to an OVFL exception stk frame	#
1132#	If UNFL exception (opclass 3):					#
1133#	- The system stack is changed to an UNFL exception stack frame	#
1134#	If Trace exception enabled:					#
1135#	- The system stack is changed to a Trace exception stack frame	#
1136#	Else: (normal case)						#
1137#	- Correct result has been stored as appropriate			#
1138#									#
1139# ALGORITHM ***********************************************************	#
1140#	Two main instruction types can enter here: (1) DENORM or UNNORM	#
1141# unimplemented data types. These can be either opclass 0,2 or 3	#
1142# instructions, and (2) PACKED unimplemented data format instructions	#
1143# also of opclasses 0,2, or 3.						#
1144#	For UNNORM/DENORM opclass 0 and 2, the handler fetches the src	#
1145# operand from the fsave state frame and the dst operand (if dyadic)	#
1146# from the FP register file. The instruction is then emulated by	#
1147# choosing an emulation routine from a table of routines indexed by	#
1148# instruction type. Once the instruction has been emulated and result	#
1149# saved, then we check to see if any enabled exceptions resulted from	#
1150# instruction emulation. If none, then we exit through the "callout"	#
1151# _fpsp_done(). If there is an enabled FP exception, then we insert	#
1152# this exception into the FPU in the fsave state frame and then exit	#
1153# through _fpsp_done().							#
1154#	PACKED opclass 0 and 2 is similar in how the instruction is	#
1155# emulated and exceptions handled. The differences occur in how the	#
1156# handler loads the packed op (by calling get_packed() routine) and	#
1157# by the fact that a Trace exception could be pending for PACKED ops.	#
1158# If a Trace exception is pending, then the current exception stack	#
1159# frame is changed to a Trace exception stack frame and an exit is	#
1160# made through _real_trace().						#
1161#	For UNNORM/DENORM opclass 3, the actual move out to memory is	#
1162# performed by calling the routine fout(). If no exception should occur	#
1163# as the result of emulation, then an exit either occurs through	#
1164# _fpsp_done() or through _real_trace() if a Trace exception is pending	#
1165# (a Trace stack frame must be created here, too). If an FP exception	#
1166# should occur, then we must create an exception stack frame of that	#
1167# type and jump to either _real_snan(), _real_operr(), _real_inex(),	#
1168# _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3	#
1169# emulation is performed in a similar manner.				#
1170#									#
1171#########################################################################
1172
1173#
1174# (1) DENORM and UNNORM (unimplemented) data types:
1175#
1176#				post-instruction
1177#				*****************
1178#				*      EA	*
1179#	 pre-instruction	*		*
1180#	*****************	*****************
1181#	* 0x0 *  0x0dc  *	* 0x3 *  0x0dc  *
1182#	*****************	*****************
1183#	*     Next	*	*     Next	*
1184#	*      PC	*	*      PC	*
1185#	*****************	*****************
1186#	*      SR	*	*      SR	*
1187#	*****************	*****************
1188#
1189# (2) PACKED format (unsupported) opclasses two and three:
1190#	*****************
1191#	*      EA	*
1192#	*		*
1193#	*****************
1194#	* 0x2 *  0x0dc	*
1195#	*****************
1196#	*     Next	*
1197#	*      PC	*
1198#	*****************
1199#	*      SR	*
1200#	*****************
1201#
1202	global		_fpsp_unsupp
1203_fpsp_unsupp:
1204
1205	link.w		%a6,&-LOCAL_SIZE	# init stack frame
1206
1207	fsave		FP_SRC(%a6)		# save fp state
1208
1209	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1210	fmovm.l		%fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
1211	fmovm.x		&0xc0,EXC_FPREGS(%a6)	# save fp0-fp1 on stack
1212
1213	btst		&0x5,EXC_SR(%a6)	# user or supervisor mode?
1214	bne.b		fu_s
1215fu_u:
1216	mov.l		%usp,%a0		# fetch user stack pointer
1217	mov.l		%a0,EXC_A7(%a6)		# save on stack
1218	bra.b		fu_cont
1219# if the exception is an opclass zero or two unimplemented data type
1220# exception, then the a7' calculated here is wrong since it doesn't
1221# stack an ea. however, we don't need an a7' for this case anyways.
1222fu_s:
1223	lea		0x4+EXC_EA(%a6),%a0	# load old a7'
1224	mov.l		%a0,EXC_A7(%a6)		# save on stack
1225
1226fu_cont:
1227
1228# the FPIAR holds the "current PC" of the faulting instruction
1229# the FPIAR should be set correctly for ALL exceptions passing through
1230# this point.
1231	mov.l		USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
1232	mov.l		EXC_EXTWPTR(%a6),%a0	# fetch instruction addr
1233	addq.l		&0x4,EXC_EXTWPTR(%a6)	# incr instruction ptr
1234	bsr.l		_imem_read_long		# fetch the instruction words
1235	mov.l		%d0,EXC_OPWORD(%a6)	# store OPWORD and EXTWORD
1236
1237############################
1238
1239	clr.b		SPCOND_FLG(%a6)		# clear special condition flag
1240
1241# Separate opclass three (fpn-to-mem) ops since they have a different
1242# stack frame and protocol.
1243	btst		&0x5,EXC_CMDREG(%a6)	# is it an fmove out?
1244	bne.w		fu_out			# yes
1245
1246# Separate packed opclass two instructions.
1247	bfextu		EXC_CMDREG(%a6){&0:&6},%d0
1248	cmpi.b		%d0,&0x13
1249	beq.w		fu_in_pack
1250
1251
1252# I'm not sure at this point what FPSR bits are valid for this instruction.
1253# so, since the emulation routines re-create them anyways, zero exception field
1254	andi.l		&0x00ff00ff,USER_FPSR(%a6) # zero exception field
1255
1256	fmov.l		&0x0,%fpcr		# zero current control regs
1257	fmov.l		&0x0,%fpsr
1258
1259# Opclass two w/ memory-to-fpn operation will have an incorrect extended
1260# precision format if the src format was single or double and the
1261# source data type was an INF, NAN, DENORM, or UNNORM
1262	lea		FP_SRC(%a6),%a0		# pass ptr to input
1263	bsr.l		fix_skewed_ops
1264
1265# we don't know whether the src operand or the dst operand (or both) is the
1266# UNNORM or DENORM. call the function that tags the operand type. if the
1267# input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
1268	lea		FP_SRC(%a6),%a0		# pass: ptr to src op
1269	bsr.l		set_tag_x		# tag the operand type
1270	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
1271	bne.b		fu_op2			# no
1272	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
1273
1274fu_op2:
1275	mov.b		%d0,STAG(%a6)		# save src optype tag
1276
1277	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1278
1279# bit five of the fp extension word separates the monadic and dyadic operations
1280# at this point
1281	btst		&0x5,1+EXC_CMDREG(%a6)	# is operation monadic or dyadic?
1282	beq.b		fu_extract		# monadic
1283	cmpi.b		1+EXC_CMDREG(%a6),&0x3a	# is operation an ftst?
1284	beq.b		fu_extract		# yes, so it's monadic, too
1285
1286	bsr.l		load_fpn2		# load dst into FP_DST
1287
1288	lea		FP_DST(%a6),%a0		# pass: ptr to dst op
1289	bsr.l		set_tag_x		# tag the operand type
1290	cmpi.b		%d0,&UNNORM		# is operand an UNNORM?
1291	bne.b		fu_op2_done		# no
1292	bsr.l		unnorm_fix		# yes; convert to NORM,DENORM,or ZERO
1293fu_op2_done:
1294	mov.b		%d0,DTAG(%a6)		# save dst optype tag
1295
1296fu_extract:
1297	clr.l		%d0
1298	mov.b		FPCR_MODE(%a6),%d0	# fetch rnd mode/prec
1299
1300	bfextu		1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
1301
1302	lea		FP_SRC(%a6),%a0
1303	lea		FP_DST(%a6),%a1
1304
1305	mov.l		(tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
1306	jsr		(tbl_unsupp.l,%pc,%d1.l*1)
1307
1308#
1309# Exceptions in order of precedence:
1310#	BSUN	: none
1311#	SNAN	: all dyadic ops
1312#	OPERR	: fsqrt(-NORM)
1313#	OVFL	: all except ftst,fcmp
1314#	UNFL	: all except ftst,fcmp
1315#	DZ	: fdiv
1316#	INEX2	: all except ftst,fcmp
1317#	INEX1	: none (packed doesn't go through here)
1318#
1319
1320# we determine the highest priority exception(if any) set by the
1321# emulation routine that has also been enabled by the user.
1322	mov.b		FPCR_ENABLE(%a6),%d0	# fetch exceptions set
1323	bne.b		fu_in_ena		# some are enabled
1324
1325fu_in_cont:
1326# fcmp and ftst do not store any result.
1327	mov.b		1+EXC_CMDREG(%a6),%d0	# fetch extension
1328	andi.b		&0x38,%d0		# extract bits 3-5
1329	cmpi.b		%d0,&0x38		# is instr fcmp or ftst?
1330	beq.b		fu_in_exit		# yes
1331
1332	bfextu		EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
1333	bsr.l		store_fpreg		# store the result
1334
1335fu_in_exit:
1336
1337	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
1338	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1339	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1340
1341	unlk		%a6
1342
1343	bra.l		_fpsp_done
1344
1345fu_in_ena:
1346	and.b		FPSR_EXCEPT(%a6),%d0	# keep only ones enabled
1347	bfffo		%d0{&24:&8},%d0		# find highest priority exception
1348	bne.b		fu_in_exc		# there is at least one set
1349
1350#
1351# No exceptions occurred that were also enabled. Now:
1352#
1353#	if (OVFL && ovfl_disabled && inexact_enabled) {
1354#	    branch to _real_inex() (even if the result was exact!);
1355#	} else {
1356#	    save the result in the proper fp reg (unless the op is fcmp or ftst);
1357#	    return;
1358#	}
1359#
1360	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
1361	beq.b		fu_in_cont		# no
1362
1363fu_in_ovflchk:
1364	btst		&inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
1365	beq.b		fu_in_cont		# no
1366	bra.w		fu_in_exc_ovfl		# go insert overflow frame
1367
1368#
1369# An exception occurred and that exception was enabled:
1370#
1371#	shift enabled exception field into lo byte of d0;
1372#	if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
1373#	    ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
1374#		/*
1375#		 * this is the case where we must call _real_inex() now or else
1376#		 * there will be no other way to pass it the exceptional operand
1377#		 */
1378#		call _real_inex();
1379#	} else {
1380#		restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
1381#	}
1382#
1383fu_in_exc:
1384	subi.l		&24,%d0			# fix offset to be 0-8
1385	cmpi.b		%d0,&0x6		# is exception INEX? (6)
1386	bne.b		fu_in_exc_exit		# no
1387
1388# the enabled exception was inexact
1389	btst		&unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
1390	bne.w		fu_in_exc_unfl		# yes
1391	btst		&ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
1392	bne.w		fu_in_exc_ovfl		# yes
1393
1394# here, we insert the correct fsave status value into the fsave frame for the
1395# corresponding exception. the operand in the fsave frame should be the original
1396# src operand.
1397fu_in_exc_exit:
1398	mov.l		%d0,-(%sp)		# save d0
1399	bsr.l		funimp_skew		# skew sgl or dbl inputs
1400	mov.l		(%sp)+,%d0		# restore d0
1401
1402	mov.w		(tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
1403
1404	fmovm.x		EXC_FPREGS(%a6),&0xc0	# restore fp0/fp1
1405	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
1406	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1407
1408	frestore	FP_SRC(%a6)		# restore src op
1409
1410	unlk		%a6
1411
1412	bra.l		_fpsp_done
1413
1414tbl_except:
1415	short		0xe000,0xe006,0xe004,0xe005
1416	short		0xe003,0xe002,0xe001,0xe001
1417
1418fu_in_exc_unfl:
1419	mov.w		&0x4,%d0
1420	bra.b		fu_in_exc_exit
1421fu_in_exc_ovfl:
1422	mov.w		&0x03,%d0
1423	bra.b		fu_in_exc_exit
1424
1425# If the input operand to this operation was opclass two and a single
1426# or double precision denorm, inf, or nan, the operand needs to be
1427# "corrected" in order to have the proper equivalent extended precision
1428# number.
1429	global		fix_skewed_ops
1430fix_skewed_ops:
1431	bfextu		EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
1432	cmpi.b		%d0,&0x11		# is class = 2 & fmt = sgl?
1433	beq.b		fso_sgl			# yes
1434	cmpi.b		%d0,&0x15		# is class = 2 & fmt = dbl?
1435	beq.b		fso_dbl			# yes
1436	rts					# no
1437
1438fso_sgl:
1439	mov.w		LOCAL_EX(%a0),%d0	# fetch src exponent
1440	andi.w		&0x7fff,%d0		# strip sign
1441	cmpi.w		%d0,&0x3f80		# is |exp| == $3f80?
1442	beq.b		fso_sgl_dnrm_zero	# yes
1443	cmpi.w		%d0,&0x407f		# no; is |exp| == $407f?
1444	beq.b		fso_infnan		# yes
1445	rts					# no
1446
1447fso_sgl_dnrm_zero:
1448	andi.l		&0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1449	beq.b		fso_zero		# it's a skewed zero
1450fso_sgl_dnrm:
1451# here, we count on norm not to alter a0...
1452	bsr.l		norm			# normalize mantissa
1453	neg.w		%d0			# -shft amt
1454	addi.w		&0x3f81,%d0		# adjust new exponent
1455	andi.w		&0x8000,LOCAL_EX(%a0)	# clear old exponent
1456	or.w		%d0,LOCAL_EX(%a0)	# insert new exponent
1457	rts
1458
1459fso_zero:
1460	andi.w		&0x8000,LOCAL_EX(%a0)	# clear bogus exponent
1461	rts
1462
1463fso_infnan:
1464	andi.b		&0x7f,LOCAL_HI(%a0)	# clear j-bit
1465	ori.w		&0x7fff,LOCAL_EX(%a0)	# make exponent = $7fff
1466	rts
1467
1468fso_dbl:
1469	mov.w		LOCAL_EX(%a0),%d0	# fetch src exponent
1470	andi.w		&0x7fff,%d0		# strip sign
1471	cmpi.w		%d0,&0x3c00		# is |exp| == $3c00?
1472	beq.b		fso_dbl_dnrm_zero	# yes
1473	cmpi.w		%d0,&0x43ff		# no; is |exp| == $43ff?
1474	beq.b		fso_infnan		# yes
1475	rts					# no
1476
1477fso_dbl_dnrm_zero:
1478	andi.l		&0x7fffffff,LOCAL_HI(%a0) # clear j-bit
1479	bne.b		fso_dbl_dnrm		# it's a skewed denorm
1480	tst.l		LOCAL_LO(%a0)		# is it a zero?
1481	beq.b		fso_zero		# yes
1482fso_dbl_dnrm:
1483# here, we count on norm not to alter a0...
1484	bsr.l		norm			# normalize mantissa
1485	neg.w		%d0			# -shft amt
1486	addi.w		&0x3c01,%d0		# adjust new exponent
1487	andi.w		&0x8000,LOCAL_EX(%a0)	# clear old exponent
1488	or.w		%d0,LOCAL_EX(%a0)	# insert new exponent
1489	rts
1490
1491#################################################################
1492
1493# fmove out took an unimplemented data type exception.
1494# the src operand is in FP_SRC. Call _fout() to write out the result and
1495# to determine which exceptions, if any, to take.
1496fu_out:
1497
1498# Separate packed move outs from the UNNORM and DENORM move outs.
1499	bfextu		EXC_CMDREG(%a6){&3:&3},%d0
1500	cmpi.b		%d0,&0x3
1501	beq.w		fu_out_pack
1502	cmpi.b		%d0,&0x7
1503	beq.w		fu_out_pack
1504
1505
1506# I'm not sure

Large files files are truncated, but you can click here to view the full file