Linux Audio

Check our new training course

Loading...
v5.9
   1/*
   2 * fp_util.S
   3 *
   4 * Copyright Roman Zippel, 1997.  All rights reserved.
   5 *
   6 * Redistribution and use in source and binary forms, with or without
   7 * modification, are permitted provided that the following conditions
   8 * are met:
   9 * 1. Redistributions of source code must retain the above copyright
  10 *    notice, and the entire permission notice in its entirety,
  11 *    including the disclaimer of warranties.
  12 * 2. Redistributions in binary form must reproduce the above copyright
  13 *    notice, this list of conditions and the following disclaimer in the
  14 *    documentation and/or other materials provided with the distribution.
  15 * 3. The name of the author may not be used to endorse or promote
  16 *    products derived from this software without specific prior
  17 *    written permission.
  18 *
  19 * ALTERNATIVELY, this product may be distributed under the terms of
  20 * the GNU General Public License, in which case the provisions of the GPL are
  21 * required INSTEAD OF the above restrictions.  (This clause is
  22 * necessary due to a potential bad interaction between the GPL and
  23 * the restrictions contained in a BSD-style copyright.)
  24 *
  25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  35 * OF THE POSSIBILITY OF SUCH DAMAGE.
  36 */
  37
  38#include "fp_emu.h"
  39
  40/*
  41 * Here are lots of conversion and normalization functions mainly
  42 * used by fp_scan.S
  43 * Note that these functions are optimized for "normal" numbers,
  44 * these are handled first and exit as fast as possible, this is
  45 * especially important for fp_normalize_ext/fp_conv_ext2ext, as
  46 * it's called very often.
  47 * The register usage is optimized for fp_scan.S and which register
  48 * is currently at that time unused, be careful if you want change
  49 * something here. %d0 and %d1 is always usable, sometimes %d2 (or
  50 * only the lower half) most function have to return the %a0
  51 * unmodified, so that the caller can immediately reuse it.
  52 */
  53
  54	.globl	fp_ill, fp_end
  55
  56	| exits from fp_scan:
  57	| illegal instruction
  58fp_ill:
  59	printf	,"fp_illegal\n"
  60	rts
  61	| completed instruction
  62fp_end:
  63	tst.l	(TASK_MM-8,%a2)
  64	jmi	1f
  65	tst.l	(TASK_MM-4,%a2)
  66	jmi	1f
  67	tst.l	(TASK_MM,%a2)
  68	jpl	2f
  691:	printf	,"oops:%p,%p,%p\n",3,%a2@(TASK_MM-8),%a2@(TASK_MM-4),%a2@(TASK_MM)
  702:	clr.l	%d0
  71	rts
  72
  73	.globl	fp_conv_long2ext, fp_conv_single2ext
  74	.globl	fp_conv_double2ext, fp_conv_ext2ext
  75	.globl	fp_normalize_ext, fp_normalize_double
  76	.globl	fp_normalize_single, fp_normalize_single_fast
  77	.globl	fp_conv_ext2double, fp_conv_ext2single
  78	.globl	fp_conv_ext2long, fp_conv_ext2short
  79	.globl	fp_conv_ext2byte
  80	.globl	fp_finalrounding_single, fp_finalrounding_single_fast
  81	.globl	fp_finalrounding_double
  82	.globl	fp_finalrounding, fp_finaltest, fp_final
  83
  84/*
  85 * First several conversion functions from a source operand
  86 * into the extended format. Note, that only fp_conv_ext2ext
  87 * normalizes the number and is always called after the other
  88 * conversion functions, which only move the information into
  89 * fp_ext structure.
  90 */
  91
  92	| fp_conv_long2ext:
  93	|
  94	| args:	%d0 = source (32-bit long)
  95	|	%a0 = destination (ptr to struct fp_ext)
  96
  97fp_conv_long2ext:
  98	printf	PCONV,"l2e: %p -> %p(",2,%d0,%a0
  99	clr.l	%d1			| sign defaults to zero
 100	tst.l	%d0
 101	jeq	fp_l2e_zero		| is source zero?
 102	jpl	1f			| positive?
 103	moveq	#1,%d1
 104	neg.l	%d0
 1051:	swap	%d1
 106	move.w	#0x3fff+31,%d1
 107	move.l	%d1,(%a0)+		| set sign / exp
 108	move.l	%d0,(%a0)+		| set mantissa
 109	clr.l	(%a0)
 110	subq.l	#8,%a0			| restore %a0
 111	printx	PCONV,%a0@
 112	printf	PCONV,")\n"
 113	rts
 114	| source is zero
 115fp_l2e_zero:
 116	clr.l	(%a0)+
 117	clr.l	(%a0)+
 118	clr.l	(%a0)
 119	subq.l	#8,%a0
 120	printx	PCONV,%a0@
 121	printf	PCONV,")\n"
 122	rts
 123
 124	| fp_conv_single2ext
 125	| args:	%d0 = source (single-precision fp value)
 126	|	%a0 = dest (struct fp_ext *)
 127
 128fp_conv_single2ext:
 129	printf	PCONV,"s2e: %p -> %p(",2,%d0,%a0
 130	move.l	%d0,%d1
 131	lsl.l	#8,%d0			| shift mantissa
 132	lsr.l	#8,%d1			| exponent / sign
 133	lsr.l	#7,%d1
 134	lsr.w	#8,%d1
 135	jeq	fp_s2e_small		| zero / denormal?
 136	cmp.w	#0xff,%d1		| NaN / Inf?
 137	jeq	fp_s2e_large
 138	bset	#31,%d0			| set explizit bit
 139	add.w	#0x3fff-0x7f,%d1	| re-bias the exponent.
 1409:	move.l	%d1,(%a0)+		| fp_ext.sign, fp_ext.exp
 141	move.l	%d0,(%a0)+		| high lword of fp_ext.mant
 142	clr.l	(%a0)			| low lword = 0
 143	subq.l	#8,%a0
 144	printx	PCONV,%a0@
 145	printf	PCONV,")\n"
 146	rts
 147	| zeros and denormalized
 148fp_s2e_small:
 149	| exponent is zero, so explizit bit is already zero too
 150	tst.l	%d0
 151	jeq	9b
 152	move.w	#0x4000-0x7f,%d1
 153	jra	9b
 154	| infinities and NAN
 155fp_s2e_large:
 156	bclr	#31,%d0			| clear explizit bit
 157	move.w	#0x7fff,%d1
 158	jra	9b
 159
 160fp_conv_double2ext:
 161#ifdef FPU_EMU_DEBUG
 162	getuser.l %a1@(0),%d0,fp_err_ua2,%a1
 163	getuser.l %a1@(4),%d1,fp_err_ua2,%a1
 164	printf	PCONV,"d2e: %p%p -> %p(",3,%d0,%d1,%a0
 165#endif
 166	getuser.l (%a1)+,%d0,fp_err_ua2,%a1
 167	move.l	%d0,%d1
 168	lsl.l	#8,%d0			| shift high mantissa
 169	lsl.l	#3,%d0
 170	lsr.l	#8,%d1			| exponent / sign
 171	lsr.l	#7,%d1
 172	lsr.w	#5,%d1
 173	jeq	fp_d2e_small		| zero / denormal?
 174	cmp.w	#0x7ff,%d1		| NaN / Inf?
 175	jeq	fp_d2e_large
 176	bset	#31,%d0			| set explizit bit
 177	add.w	#0x3fff-0x3ff,%d1	| re-bias the exponent.
 1789:	move.l	%d1,(%a0)+		| fp_ext.sign, fp_ext.exp
 179	move.l	%d0,(%a0)+
 180	getuser.l (%a1)+,%d0,fp_err_ua2,%a1
 181	move.l	%d0,%d1
 182	lsl.l	#8,%d0
 183	lsl.l	#3,%d0
 184	move.l	%d0,(%a0)
 185	moveq	#21,%d0
 186	lsr.l	%d0,%d1
 187	or.l	%d1,-(%a0)
 188	subq.l	#4,%a0
 189	printx	PCONV,%a0@
 190	printf	PCONV,")\n"
 191	rts
 192	| zeros and denormalized
 193fp_d2e_small:
 194	| exponent is zero, so explizit bit is already zero too
 195	tst.l	%d0
 196	jeq	9b
 197	move.w	#0x4000-0x3ff,%d1
 198	jra	9b
 199	| infinities and NAN
 200fp_d2e_large:
 201	bclr	#31,%d0			| clear explizit bit
 202	move.w	#0x7fff,%d1
 203	jra	9b
 204
 205	| fp_conv_ext2ext:
 206	| originally used to get longdouble from userspace, now it's
 207	| called before arithmetic operations to make sure the number
 208	| is normalized [maybe rename it?].
 209	| args:	%a0 = dest (struct fp_ext *)
 210	| returns 0 in %d0 for a NaN, otherwise 1
 211
 212fp_conv_ext2ext:
 213	printf	PCONV,"e2e: %p(",1,%a0
 214	printx	PCONV,%a0@
 215	printf	PCONV,"), "
 216	move.l	(%a0)+,%d0
 217	cmp.w	#0x7fff,%d0		| Inf / NaN?
 218	jeq	fp_e2e_large
 219	move.l	(%a0),%d0
 220	jpl	fp_e2e_small		| zero / denorm?
 221	| The high bit is set, so normalization is irrelevant.
 222fp_e2e_checkround:
 223	subq.l	#4,%a0
 224#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 225	move.b	(%a0),%d0
 226	jne	fp_e2e_round
 227#endif
 228	printf	PCONV,"%p(",1,%a0
 229	printx	PCONV,%a0@
 230	printf	PCONV,")\n"
 231	moveq	#1,%d0
 232	rts
 233#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 234fp_e2e_round:
 235	fp_set_sr FPSR_EXC_INEX2
 236	clr.b	(%a0)
 237	move.w	(FPD_RND,FPDATA),%d2
 238	jne	fp_e2e_roundother	| %d2 == 0, round to nearest
 239	tst.b	%d0			| test guard bit
 240	jpl	9f			| zero is closer
 241	btst	#0,(11,%a0)		| test lsb bit
 242	jne	fp_e2e_doroundup	| round to infinity
 243	lsl.b	#1,%d0			| check low bits
 244	jeq	9f			| round to zero
 245fp_e2e_doroundup:
 246	addq.l	#1,(8,%a0)
 247	jcc	9f
 248	addq.l	#1,(4,%a0)
 249	jcc	9f
 250	move.w	#0x8000,(4,%a0)
 251	addq.w	#1,(2,%a0)
 2529:	printf	PNORM,"%p(",1,%a0
 253	printx	PNORM,%a0@
 254	printf	PNORM,")\n"
 255	rts
 256fp_e2e_roundother:
 257	subq.w	#2,%d2
 258	jcs	9b			| %d2 < 2, round to zero
 259	jhi	1f			| %d2 > 2, round to +infinity
 260	tst.b	(1,%a0)			| to -inf
 261	jne	fp_e2e_doroundup	| negative, round to infinity
 262	jra	9b			| positive, round to zero
 2631:	tst.b	(1,%a0)			| to +inf
 264	jeq	fp_e2e_doroundup	| positive, round to infinity
 265	jra	9b			| negative, round to zero
 266#endif
 267	| zeros and subnormals:
 268	| try to normalize these anyway.
 269fp_e2e_small:
 270	jne	fp_e2e_small1		| high lword zero?
 271	move.l	(4,%a0),%d0
 272	jne	fp_e2e_small2
 273#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 274	clr.l	%d0
 275	move.b	(-4,%a0),%d0
 276	jne	fp_e2e_small3
 277#endif
 278	| Genuine zero.
 279	clr.w	-(%a0)
 280	subq.l	#2,%a0
 281	printf	PNORM,"%p(",1,%a0
 282	printx	PNORM,%a0@
 283	printf	PNORM,")\n"
 284	moveq	#1,%d0
 285	rts
 286	| definitely subnormal, need to shift all 64 bits
 287fp_e2e_small1:
 288	bfffo	%d0{#0,#32},%d1
 289	move.w	-(%a0),%d2
 290	sub.w	%d1,%d2
 291	jcc	1f
 292	| Pathologically small, denormalize.
 293	add.w	%d2,%d1
 294	clr.w	%d2
 2951:	move.w	%d2,(%a0)+
 296	move.w	%d1,%d2
 297	jeq	fp_e2e_checkround
 298	| fancy 64-bit double-shift begins here
 299	lsl.l	%d2,%d0
 300	move.l	%d0,(%a0)+
 301	move.l	(%a0),%d0
 302	move.l	%d0,%d1
 303	lsl.l	%d2,%d0
 304	move.l	%d0,(%a0)
 305	neg.w	%d2
 306	and.w	#0x1f,%d2
 307	lsr.l	%d2,%d1
 308	or.l	%d1,-(%a0)
 309#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 310fp_e2e_extra1:
 311	clr.l	%d0
 312	move.b	(-4,%a0),%d0
 313	neg.w	%d2
 314	add.w	#24,%d2
 315	jcc	1f
 316	clr.b	(-4,%a0)
 317	lsl.l	%d2,%d0
 318	or.l	%d0,(4,%a0)
 319	jra	fp_e2e_checkround
 3201:	addq.w	#8,%d2
 321	lsl.l	%d2,%d0
 322	move.b	%d0,(-4,%a0)
 323	lsr.l	#8,%d0
 324	or.l	%d0,(4,%a0)
 325#endif
 326	jra	fp_e2e_checkround
 327	| pathologically small subnormal
 328fp_e2e_small2:
 329	bfffo	%d0{#0,#32},%d1
 330	add.w	#32,%d1
 331	move.w	-(%a0),%d2
 332	sub.w	%d1,%d2
 333	jcc	1f
 334	| Beyond pathologically small, denormalize.
 335	add.w	%d2,%d1
 336	clr.w	%d2
 3371:	move.w	%d2,(%a0)+
 338	ext.l	%d1
 339	jeq	fp_e2e_checkround
 340	clr.l	(4,%a0)
 341	sub.w	#32,%d2
 342	jcs	1f
 343	lsl.l	%d1,%d0			| lower lword needs only to be shifted
 344	move.l	%d0,(%a0)		| into the higher lword
 345#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 346	clr.l	%d0
 347	move.b	(-4,%a0),%d0
 348	clr.b	(-4,%a0)
 349	neg.w	%d1
 350	add.w	#32,%d1
 351	bfins	%d0,(%a0){%d1,#8}
 352#endif
 353	jra	fp_e2e_checkround
 3541:	neg.w	%d1			| lower lword is splitted between
 355	bfins	%d0,(%a0){%d1,#32}	| higher and lower lword
 356#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
 357	jra	fp_e2e_checkround
 358#else
 359	move.w	%d1,%d2
 360	jra	fp_e2e_extra1
 361	| These are extremely small numbers, that will mostly end up as zero
 362	| anyway, so this is only important for correct rounding.
 363fp_e2e_small3:
 364	bfffo	%d0{#24,#8},%d1
 365	add.w	#40,%d1
 366	move.w	-(%a0),%d2
 367	sub.w	%d1,%d2
 368	jcc	1f
 369	| Pathologically small, denormalize.
 370	add.w	%d2,%d1
 371	clr.w	%d2
 3721:	move.w	%d2,(%a0)+
 373	ext.l	%d1
 374	jeq	fp_e2e_checkround
 375	cmp.w	#8,%d1
 376	jcs	2f
 3771:	clr.b	(-4,%a0)
 378	sub.w	#64,%d1
 379	jcs	1f
 380	add.w	#24,%d1
 381	lsl.l	%d1,%d0
 382	move.l	%d0,(%a0)
 383	jra	fp_e2e_checkround
 3841:	neg.w	%d1
 385	bfins	%d0,(%a0){%d1,#8}
 386	jra	fp_e2e_checkround
 3872:	lsl.l	%d1,%d0
 388	move.b	%d0,(-4,%a0)
 389	lsr.l	#8,%d0
 390	move.b	%d0,(7,%a0)
 391	jra	fp_e2e_checkround
 392#endif
 3931:	move.l	%d0,%d1			| lower lword is splitted between
 394	lsl.l	%d2,%d0			| higher and lower lword
 395	move.l	%d0,(%a0)
 396	move.l	%d1,%d0
 397	neg.w	%d2
 398	add.w	#32,%d2
 399	lsr.l	%d2,%d0
 400	move.l	%d0,-(%a0)
 401	jra	fp_e2e_checkround
 402	| Infinities and NaNs
 403fp_e2e_large:
 404	move.l	(%a0)+,%d0
 405	jne	3f
 4061:	tst.l	(%a0)
 407	jne	4f
 408	moveq	#1,%d0
 4092:	subq.l	#8,%a0
 410	printf	PCONV,"%p(",1,%a0
 411	printx	PCONV,%a0@
 412	printf	PCONV,")\n"
 413	rts
 414	| we have maybe a NaN, shift off the highest bit
 4153:	lsl.l	#1,%d0
 416	jeq	1b
 417	| we have a NaN, clear the return value
 4184:	clrl	%d0
 419	jra	2b
 420
 421
 422/*
 423 * Normalization functions.  Call these on the output of general
 424 * FP operators, and before any conversion into the destination
 425 * formats. fp_normalize_ext has always to be called first, the
 426 * following conversion functions expect an already normalized
 427 * number.
 428 */
 429
 430	| fp_normalize_ext:
 431	| normalize an extended in extended (unpacked) format, basically
 432	| it does the same as fp_conv_ext2ext, additionally it also does
 433	| the necessary postprocessing checks.
 434	| args:	%a0 (struct fp_ext *)
 435	| NOTE: it does _not_ modify %a0/%a1 and the upper word of %d2
 436
 437fp_normalize_ext:
 438	printf	PNORM,"ne: %p(",1,%a0
 439	printx	PNORM,%a0@
 440	printf	PNORM,"), "
 441	move.l	(%a0)+,%d0
 442	cmp.w	#0x7fff,%d0		| Inf / NaN?
 443	jeq	fp_ne_large
 444	move.l	(%a0),%d0
 445	jpl	fp_ne_small		| zero / denorm?
 446	| The high bit is set, so normalization is irrelevant.
 447fp_ne_checkround:
 448	subq.l	#4,%a0
 449#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 450	move.b	(%a0),%d0
 451	jne	fp_ne_round
 452#endif
 453	printf	PNORM,"%p(",1,%a0
 454	printx	PNORM,%a0@
 455	printf	PNORM,")\n"
 456	rts
 457#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 458fp_ne_round:
 459	fp_set_sr FPSR_EXC_INEX2
 460	clr.b	(%a0)
 461	move.w	(FPD_RND,FPDATA),%d2
 462	jne	fp_ne_roundother	| %d2 == 0, round to nearest
 463	tst.b	%d0			| test guard bit
 464	jpl	9f			| zero is closer
 465	btst	#0,(11,%a0)		| test lsb bit
 466	jne	fp_ne_doroundup		| round to infinity
 467	lsl.b	#1,%d0			| check low bits
 468	jeq	9f			| round to zero
 469fp_ne_doroundup:
 470	addq.l	#1,(8,%a0)
 471	jcc	9f
 472	addq.l	#1,(4,%a0)
 473	jcc	9f
 474	addq.w	#1,(2,%a0)
 475	move.w	#0x8000,(4,%a0)
 4769:	printf	PNORM,"%p(",1,%a0
 477	printx	PNORM,%a0@
 478	printf	PNORM,")\n"
 479	rts
 480fp_ne_roundother:
 481	subq.w	#2,%d2
 482	jcs	9b			| %d2 < 2, round to zero
 483	jhi	1f			| %d2 > 2, round to +infinity
 484	tst.b	(1,%a0)			| to -inf
 485	jne	fp_ne_doroundup		| negative, round to infinity
 486	jra	9b			| positive, round to zero
 4871:	tst.b	(1,%a0)			| to +inf
 488	jeq	fp_ne_doroundup		| positive, round to infinity
 489	jra	9b			| negative, round to zero
 490#endif
 491	| Zeros and subnormal numbers
 492	| These are probably merely subnormal, rather than "denormalized"
 493	|  numbers, so we will try to make them normal again.
 494fp_ne_small:
 495	jne	fp_ne_small1		| high lword zero?
 496	move.l	(4,%a0),%d0
 497	jne	fp_ne_small2
 498#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 499	clr.l	%d0
 500	move.b	(-4,%a0),%d0
 501	jne	fp_ne_small3
 502#endif
 503	| Genuine zero.
 504	clr.w	-(%a0)
 505	subq.l	#2,%a0
 506	printf	PNORM,"%p(",1,%a0
 507	printx	PNORM,%a0@
 508	printf	PNORM,")\n"
 509	rts
 510	| Subnormal.
 511fp_ne_small1:
 512	bfffo	%d0{#0,#32},%d1
 513	move.w	-(%a0),%d2
 514	sub.w	%d1,%d2
 515	jcc	1f
 516	| Pathologically small, denormalize.
 517	add.w	%d2,%d1
 518	clr.w	%d2
 519	fp_set_sr FPSR_EXC_UNFL
 5201:	move.w	%d2,(%a0)+
 521	move.w	%d1,%d2
 522	jeq	fp_ne_checkround
 523	| This is exactly the same 64-bit double shift as seen above.
 524	lsl.l	%d2,%d0
 525	move.l	%d0,(%a0)+
 526	move.l	(%a0),%d0
 527	move.l	%d0,%d1
 528	lsl.l	%d2,%d0
 529	move.l	%d0,(%a0)
 530	neg.w	%d2
 531	and.w	#0x1f,%d2
 532	lsr.l	%d2,%d1
 533	or.l	%d1,-(%a0)
 534#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 535fp_ne_extra1:
 536	clr.l	%d0
 537	move.b	(-4,%a0),%d0
 538	neg.w	%d2
 539	add.w	#24,%d2
 540	jcc	1f
 541	clr.b	(-4,%a0)
 542	lsl.l	%d2,%d0
 543	or.l	%d0,(4,%a0)
 544	jra	fp_ne_checkround
 5451:	addq.w	#8,%d2
 546	lsl.l	%d2,%d0
 547	move.b	%d0,(-4,%a0)
 548	lsr.l	#8,%d0
 549	or.l	%d0,(4,%a0)
 550#endif
 551	jra	fp_ne_checkround
 552	| May or may not be subnormal, if so, only 32 bits to shift.
 553fp_ne_small2:
 554	bfffo	%d0{#0,#32},%d1
 555	add.w	#32,%d1
 556	move.w	-(%a0),%d2
 557	sub.w	%d1,%d2
 558	jcc	1f
 559	| Beyond pathologically small, denormalize.
 560	add.w	%d2,%d1
 561	clr.w	%d2
 562	fp_set_sr FPSR_EXC_UNFL
 5631:	move.w	%d2,(%a0)+
 564	ext.l	%d1
 565	jeq	fp_ne_checkround
 566	clr.l	(4,%a0)
 567	sub.w	#32,%d1
 568	jcs	1f
 569	lsl.l	%d1,%d0			| lower lword needs only to be shifted
 570	move.l	%d0,(%a0)		| into the higher lword
 571#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 572	clr.l	%d0
 573	move.b	(-4,%a0),%d0
 574	clr.b	(-4,%a0)
 575	neg.w	%d1
 576	add.w	#32,%d1
 577	bfins	%d0,(%a0){%d1,#8}
 578#endif
 579	jra	fp_ne_checkround
 5801:	neg.w	%d1			| lower lword is splitted between
 581	bfins	%d0,(%a0){%d1,#32}	| higher and lower lword
 582#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
 583	jra	fp_ne_checkround
 584#else
 585	move.w	%d1,%d2
 586	jra	fp_ne_extra1
 587	| These are extremely small numbers, that will mostly end up as zero
 588	| anyway, so this is only important for correct rounding.
 589fp_ne_small3:
 590	bfffo	%d0{#24,#8},%d1
 591	add.w	#40,%d1
 592	move.w	-(%a0),%d2
 593	sub.w	%d1,%d2
 594	jcc	1f
 595	| Pathologically small, denormalize.
 596	add.w	%d2,%d1
 597	clr.w	%d2
 5981:	move.w	%d2,(%a0)+
 599	ext.l	%d1
 600	jeq	fp_ne_checkround
 601	cmp.w	#8,%d1
 602	jcs	2f
 6031:	clr.b	(-4,%a0)
 604	sub.w	#64,%d1
 605	jcs	1f
 606	add.w	#24,%d1
 607	lsl.l	%d1,%d0
 608	move.l	%d0,(%a0)
 609	jra	fp_ne_checkround
 6101:	neg.w	%d1
 611	bfins	%d0,(%a0){%d1,#8}
 612	jra	fp_ne_checkround
 6132:	lsl.l	%d1,%d0
 614	move.b	%d0,(-4,%a0)
 615	lsr.l	#8,%d0
 616	move.b	%d0,(7,%a0)
 617	jra	fp_ne_checkround
 618#endif
 619	| Infinities and NaNs, again, same as above.
 620fp_ne_large:
 621	move.l	(%a0)+,%d0
 622	jne	3f
 6231:	tst.l	(%a0)
 624	jne	4f
 6252:	subq.l	#8,%a0
 626	printf	PNORM,"%p(",1,%a0
 627	printx	PNORM,%a0@
 628	printf	PNORM,")\n"
 629	rts
 630	| we have maybe a NaN, shift off the highest bit
 6313:	move.l	%d0,%d1
 632	lsl.l	#1,%d1
 633	jne	4f
 634	clr.l	(-4,%a0)
 635	jra	1b
 636	| we have a NaN, test if it is signaling
 6374:	bset	#30,%d0
 638	jne	2b
 639	fp_set_sr FPSR_EXC_SNAN
 640	move.l	%d0,(-4,%a0)
 641	jra	2b
 642
 643	| these next two do rounding as per the IEEE standard.
 644	| values for the rounding modes appear to be:
 645	| 0:	Round to nearest
 646	| 1:	Round to zero
 647	| 2:	Round to -Infinity
 648	| 3:	Round to +Infinity
 649	| both functions expect that fp_normalize was already
 650	| called (and extended argument is already normalized
 651	| as far as possible), these are used if there is different
 652	| rounding precision is selected and before converting
 653	| into single/double
 654
 655	| fp_normalize_double:
 656	| normalize an extended with double (52-bit) precision
 657	| args:	 %a0 (struct fp_ext *)
 658
 659fp_normalize_double:
 660	printf	PNORM,"nd: %p(",1,%a0
 661	printx	PNORM,%a0@
 662	printf	PNORM,"), "
 663	move.l	(%a0)+,%d2
 664	tst.w	%d2
 665	jeq	fp_nd_zero		| zero / denormalized
 666	cmp.w	#0x7fff,%d2
 667	jeq	fp_nd_huge		| NaN / infinitive.
 668	sub.w	#0x4000-0x3ff,%d2	| will the exponent fit?
 669	jcs	fp_nd_small		| too small.
 670	cmp.w	#0x7fe,%d2
 671	jcc	fp_nd_large		| too big.
 672	addq.l	#4,%a0
 673	move.l	(%a0),%d0		| low lword of mantissa
 674	| now, round off the low 11 bits.
 675fp_nd_round:
 676	moveq	#21,%d1
 677	lsl.l	%d1,%d0			| keep 11 low bits.
 678	jne	fp_nd_checkround	| Are they non-zero?
 679	| nothing to do here
 6809:	subq.l	#8,%a0
 681	printf	PNORM,"%p(",1,%a0
 682	printx	PNORM,%a0@
 683	printf	PNORM,")\n"
 684	rts
 685	| Be careful with the X bit! It contains the lsb
 686	| from the shift above, it is needed for round to nearest.
 687fp_nd_checkround:
 688	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
 689	and.w	#0xf800,(2,%a0)		| clear bits 0-10
 690	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
 691	jne	2f			| %d2 == 0, round to nearest
 692	tst.l	%d0			| test guard bit
 693	jpl	9b			| zero is closer
 694	| here we test the X bit by adding it to %d2
 695	clr.w	%d2			| first set z bit, addx only clears it
 696	addx.w	%d2,%d2			| test lsb bit
 697	| IEEE754-specified "round to even" behaviour.  If the guard
 698	| bit is set, then the number is odd, so rounding works like
 699	| in grade-school arithmetic (i.e. 1.5 rounds to 2.0)
 700	| Otherwise, an equal distance rounds towards zero, so as not
 701	| to produce an odd number.  This is strange, but it is what
 702	| the standard says.
 703	jne	fp_nd_doroundup		| round to infinity
 704	lsl.l	#1,%d0			| check low bits
 705	jeq	9b			| round to zero
 706fp_nd_doroundup:
 707	| round (the mantissa, that is) towards infinity
 708	add.l	#0x800,(%a0)
 709	jcc	9b			| no overflow, good.
 710	addq.l	#1,-(%a0)		| extend to high lword
 711	jcc	1f			| no overflow, good.
 712	| Yow! we have managed to overflow the mantissa.  Since this
 713	| only happens when %d1 was 0xfffff800, it is now zero, so
 714	| reset the high bit, and increment the exponent.
 715	move.w	#0x8000,(%a0)
 716	addq.w	#1,-(%a0)
 717	cmp.w	#0x43ff,(%a0)+		| exponent now overflown?
 718	jeq	fp_nd_large		| yes, so make it infinity.
 7191:	subq.l	#4,%a0
 720	printf	PNORM,"%p(",1,%a0
 721	printx	PNORM,%a0@
 722	printf	PNORM,")\n"
 723	rts
 7242:	subq.w	#2,%d2
 725	jcs	9b			| %d2 < 2, round to zero
 726	jhi	3f			| %d2 > 2, round to +infinity
 727	| Round to +Inf or -Inf.  High word of %d2 contains the
 728	| sign of the number, by the way.
 729	swap	%d2			| to -inf
 730	tst.b	%d2
 731	jne	fp_nd_doroundup		| negative, round to infinity
 732	jra	9b			| positive, round to zero
 7333:	swap	%d2			| to +inf
 734	tst.b	%d2
 735	jeq	fp_nd_doroundup		| positive, round to infinity
 736	jra	9b			| negative, round to zero
 737	| Exponent underflow.  Try to make a denormal, and set it to
 738	| the smallest possible fraction if this fails.
 739fp_nd_small:
 740	fp_set_sr FPSR_EXC_UNFL		| set UNFL bit
 741	move.w	#0x3c01,(-2,%a0)	| 2**-1022
 742	neg.w	%d2			| degree of underflow
 743	cmp.w	#32,%d2			| single or double shift?
 744	jcc	1f
 745	| Again, another 64-bit double shift.
 746	move.l	(%a0),%d0
 747	move.l	%d0,%d1
 748	lsr.l	%d2,%d0
 749	move.l	%d0,(%a0)+
 750	move.l	(%a0),%d0
 751	lsr.l	%d2,%d0
 752	neg.w	%d2
 753	add.w	#32,%d2
 754	lsl.l	%d2,%d1
 755	or.l	%d1,%d0
 756	move.l	(%a0),%d1
 757	move.l	%d0,(%a0)
 758	| Check to see if we shifted off any significant bits
 759	lsl.l	%d2,%d1
 760	jeq	fp_nd_round		| Nope, round.
 761	bset	#0,%d0			| Yes, so set the "sticky bit".
 762	jra	fp_nd_round		| Now, round.
 763	| Another 64-bit single shift and store
 7641:	sub.w	#32,%d2
 765	cmp.w	#32,%d2			| Do we really need to shift?
 766	jcc	2f			| No, the number is too small.
 767	move.l	(%a0),%d0
 768	clr.l	(%a0)+
 769	move.l	%d0,%d1
 770	lsr.l	%d2,%d0
 771	neg.w	%d2
 772	add.w	#32,%d2
 773	| Again, check to see if we shifted off any significant bits.
 774	tst.l	(%a0)
 775	jeq	1f
 776	bset	#0,%d0			| Sticky bit.
 7771:	move.l	%d0,(%a0)
 778	lsl.l	%d2,%d1
 779	jeq	fp_nd_round
 780	bset	#0,%d0
 781	jra	fp_nd_round
 782	| Sorry, the number is just too small.
 7832:	clr.l	(%a0)+
 784	clr.l	(%a0)
 785	moveq	#1,%d0			| Smallest possible fraction,
 786	jra	fp_nd_round		| round as desired.
 787	| zero and denormalized
 788fp_nd_zero:
 789	tst.l	(%a0)+
 790	jne	1f
 791	tst.l	(%a0)
 792	jne	1f
 793	subq.l	#8,%a0
 794	printf	PNORM,"%p(",1,%a0
 795	printx	PNORM,%a0@
 796	printf	PNORM,")\n"
 797	rts				| zero.  nothing to do.
 798	| These are not merely subnormal numbers, but true denormals,
 799	| i.e. pathologically small (exponent is 2**-16383) numbers.
 800	| It is clearly impossible for even a normal extended number
 801	| with that exponent to fit into double precision, so just
 802	| write these ones off as "too darn small".
 8031:	fp_set_sr FPSR_EXC_UNFL		| Set UNFL bit
 804	clr.l	(%a0)
 805	clr.l	-(%a0)
 806	move.w	#0x3c01,-(%a0)		| i.e. 2**-1022
 807	addq.l	#6,%a0
 808	moveq	#1,%d0
 809	jra	fp_nd_round		| round.
 810	| Exponent overflow.  Just call it infinity.
 811fp_nd_large:
 812	move.w	#0x7ff,%d0
 813	and.w	(6,%a0),%d0
 814	jeq	1f
 815	fp_set_sr FPSR_EXC_INEX2
 8161:	fp_set_sr FPSR_EXC_OVFL
 817	move.w	(FPD_RND,FPDATA),%d2
 818	jne	3f			| %d2 = 0 round to nearest
 8191:	move.w	#0x7fff,(-2,%a0)
 820	clr.l	(%a0)+
 821	clr.l	(%a0)
 8222:	subq.l	#8,%a0
 823	printf	PNORM,"%p(",1,%a0
 824	printx	PNORM,%a0@
 825	printf	PNORM,")\n"
 826	rts
 8273:	subq.w	#2,%d2
 828	jcs	5f			| %d2 < 2, round to zero
 829	jhi	4f			| %d2 > 2, round to +infinity
 830	tst.b	(-3,%a0)		| to -inf
 831	jne	1b
 832	jra	5f
 8334:	tst.b	(-3,%a0)		| to +inf
 834	jeq	1b
 8355:	move.w	#0x43fe,(-2,%a0)
 836	moveq	#-1,%d0
 837	move.l	%d0,(%a0)+
 838	move.w	#0xf800,%d0
 839	move.l	%d0,(%a0)
 840	jra	2b
 841	| Infinities or NaNs
 842fp_nd_huge:
 843	subq.l	#4,%a0
 844	printf	PNORM,"%p(",1,%a0
 845	printx	PNORM,%a0@
 846	printf	PNORM,")\n"
 847	rts
 848
 849	| fp_normalize_single:
 850	| normalize an extended with single (23-bit) precision
 851	| args:	 %a0 (struct fp_ext *)
 852
 853fp_normalize_single:
 854	printf	PNORM,"ns: %p(",1,%a0
 855	printx	PNORM,%a0@
 856	printf	PNORM,") "
 857	addq.l	#2,%a0
 858	move.w	(%a0)+,%d2
 859	jeq	fp_ns_zero		| zero / denormalized
 860	cmp.w	#0x7fff,%d2
 861	jeq	fp_ns_huge		| NaN / infinitive.
 862	sub.w	#0x4000-0x7f,%d2	| will the exponent fit?
 863	jcs	fp_ns_small		| too small.
 864	cmp.w	#0xfe,%d2
 865	jcc	fp_ns_large		| too big.
 866	move.l	(%a0)+,%d0		| get high lword of mantissa
 867fp_ns_round:
 868	tst.l	(%a0)			| check the low lword
 869	jeq	1f
 870	| Set a sticky bit if it is non-zero.  This should only
 871	| affect the rounding in what would otherwise be equal-
 872	| distance situations, which is what we want it to do.
 873	bset	#0,%d0
 8741:	clr.l	(%a0)			| zap it from memory.
 875	| now, round off the low 8 bits of the hi lword.
 876	tst.b	%d0			| 8 low bits.
 877	jne	fp_ns_checkround	| Are they non-zero?
 878	| nothing to do here
 879	subq.l	#8,%a0
 880	printf	PNORM,"%p(",1,%a0
 881	printx	PNORM,%a0@
 882	printf	PNORM,")\n"
 883	rts
 884fp_ns_checkround:
 885	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
 886	clr.b	-(%a0)			| clear low byte of high lword
 887	subq.l	#3,%a0
 888	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
 889	jne	2f			| %d2 == 0, round to nearest
 890	tst.b	%d0			| test guard bit
 891	jpl	9f			| zero is closer
 892	btst	#8,%d0			| test lsb bit
 893	| round to even behaviour, see above.
 894	jne	fp_ns_doroundup		| round to infinity
 895	lsl.b	#1,%d0			| check low bits
 896	jeq	9f			| round to zero
 897fp_ns_doroundup:
 898	| round (the mantissa, that is) towards infinity
 899	add.l	#0x100,(%a0)
 900	jcc	9f			| no overflow, good.
 901	| Overflow.  This means that the %d1 was 0xffffff00, so it
 902	| is now zero.  We will set the mantissa to reflect this, and
 903	| increment the exponent (checking for overflow there too)
 904	move.w	#0x8000,(%a0)
 905	addq.w	#1,-(%a0)
 906	cmp.w	#0x407f,(%a0)+		| exponent now overflown?
 907	jeq	fp_ns_large		| yes, so make it infinity.
 9089:	subq.l	#4,%a0
 909	printf	PNORM,"%p(",1,%a0
 910	printx	PNORM,%a0@
 911	printf	PNORM,")\n"
 912	rts
 913	| check nondefault rounding modes
 9142:	subq.w	#2,%d2
 915	jcs	9b			| %d2 < 2, round to zero
 916	jhi	3f			| %d2 > 2, round to +infinity
 917	tst.b	(-3,%a0)		| to -inf
 918	jne	fp_ns_doroundup		| negative, round to infinity
 919	jra	9b			| positive, round to zero
 9203:	tst.b	(-3,%a0)		| to +inf
 921	jeq	fp_ns_doroundup		| positive, round to infinity
 922	jra	9b			| negative, round to zero
 923	| Exponent underflow.  Try to make a denormal, and set it to
 924	| the smallest possible fraction if this fails.
 925fp_ns_small:
 926	fp_set_sr FPSR_EXC_UNFL		| set UNFL bit
 927	move.w	#0x3f81,(-2,%a0)	| 2**-126
 928	neg.w	%d2			| degree of underflow
 929	cmp.w	#32,%d2			| single or double shift?
 930	jcc	2f
 931	| a 32-bit shift.
 932	move.l	(%a0),%d0
 933	move.l	%d0,%d1
 934	lsr.l	%d2,%d0
 935	move.l	%d0,(%a0)+
 936	| Check to see if we shifted off any significant bits.
 937	neg.w	%d2
 938	add.w	#32,%d2
 939	lsl.l	%d2,%d1
 940	jeq	1f
 941	bset	#0,%d0			| Sticky bit.
 942	| Check the lower lword
 9431:	tst.l	(%a0)
 944	jeq	fp_ns_round
 945	clr	(%a0)
 946	bset	#0,%d0			| Sticky bit.
 947	jra	fp_ns_round
 948	| Sorry, the number is just too small.
 9492:	clr.l	(%a0)+
 950	clr.l	(%a0)
 951	moveq	#1,%d0			| Smallest possible fraction,
 952	jra	fp_ns_round		| round as desired.
 953	| Exponent overflow.  Just call it infinity.
 954fp_ns_large:
 955	tst.b	(3,%a0)
 956	jeq	1f
 957	fp_set_sr FPSR_EXC_INEX2
 9581:	fp_set_sr FPSR_EXC_OVFL
 959	move.w	(FPD_RND,FPDATA),%d2
 960	jne	3f			| %d2 = 0 round to nearest
 9611:	move.w	#0x7fff,(-2,%a0)
 962	clr.l	(%a0)+
 963	clr.l	(%a0)
 9642:	subq.l	#8,%a0
 965	printf	PNORM,"%p(",1,%a0
 966	printx	PNORM,%a0@
 967	printf	PNORM,")\n"
 968	rts
 9693:	subq.w	#2,%d2
 970	jcs	5f			| %d2 < 2, round to zero
 971	jhi	4f			| %d2 > 2, round to +infinity
 972	tst.b	(-3,%a0)		| to -inf
 973	jne	1b
 974	jra	5f
 9754:	tst.b	(-3,%a0)		| to +inf
 976	jeq	1b
 9775:	move.w	#0x407e,(-2,%a0)
 978	move.l	#0xffffff00,(%a0)+
 979	clr.l	(%a0)
 980	jra	2b
 981	| zero and denormalized
 982fp_ns_zero:
 983	tst.l	(%a0)+
 984	jne	1f
 985	tst.l	(%a0)
 986	jne	1f
 987	subq.l	#8,%a0
 988	printf	PNORM,"%p(",1,%a0
 989	printx	PNORM,%a0@
 990	printf	PNORM,")\n"
 991	rts				| zero.  nothing to do.
 992	| These are not merely subnormal numbers, but true denormals,
 993	| i.e. pathologically small (exponent is 2**-16383) numbers.
 994	| It is clearly impossible for even a normal extended number
 995	| with that exponent to fit into single precision, so just
 996	| write these ones off as "too darn small".
 9971:	fp_set_sr FPSR_EXC_UNFL		| Set UNFL bit
 998	clr.l	(%a0)
 999	clr.l	-(%a0)
1000	move.w	#0x3f81,-(%a0)		| i.e. 2**-126
1001	addq.l	#6,%a0
1002	moveq	#1,%d0
1003	jra	fp_ns_round		| round.
1004	| Infinities or NaNs
1005fp_ns_huge:
1006	subq.l	#4,%a0
1007	printf	PNORM,"%p(",1,%a0
1008	printx	PNORM,%a0@
1009	printf	PNORM,")\n"
1010	rts
1011
1012	| fp_normalize_single_fast:
1013	| normalize an extended with single (23-bit) precision
1014	| this is only used by fsgldiv/fsgdlmul, where the
1015	| operand is not completly normalized.
1016	| args:	 %a0 (struct fp_ext *)
1017
1018fp_normalize_single_fast:
1019	printf	PNORM,"nsf: %p(",1,%a0
1020	printx	PNORM,%a0@
1021	printf	PNORM,") "
1022	addq.l	#2,%a0
1023	move.w	(%a0)+,%d2
1024	cmp.w	#0x7fff,%d2
1025	jeq	fp_nsf_huge		| NaN / infinitive.
1026	move.l	(%a0)+,%d0		| get high lword of mantissa
1027fp_nsf_round:
1028	tst.l	(%a0)			| check the low lword
1029	jeq	1f
1030	| Set a sticky bit if it is non-zero.  This should only
1031	| affect the rounding in what would otherwise be equal-
1032	| distance situations, which is what we want it to do.
1033	bset	#0,%d0
10341:	clr.l	(%a0)			| zap it from memory.
1035	| now, round off the low 8 bits of the hi lword.
1036	tst.b	%d0			| 8 low bits.
1037	jne	fp_nsf_checkround	| Are they non-zero?
1038	| nothing to do here
1039	subq.l	#8,%a0
1040	printf	PNORM,"%p(",1,%a0
1041	printx	PNORM,%a0@
1042	printf	PNORM,")\n"
1043	rts
1044fp_nsf_checkround:
1045	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
1046	clr.b	-(%a0)			| clear low byte of high lword
1047	subq.l	#3,%a0
1048	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1049	jne	2f			| %d2 == 0, round to nearest
1050	tst.b	%d0			| test guard bit
1051	jpl	9f			| zero is closer
1052	btst	#8,%d0			| test lsb bit
1053	| round to even behaviour, see above.
1054	jne	fp_nsf_doroundup		| round to infinity
1055	lsl.b	#1,%d0			| check low bits
1056	jeq	9f			| round to zero
1057fp_nsf_doroundup:
1058	| round (the mantissa, that is) towards infinity
1059	add.l	#0x100,(%a0)
1060	jcc	9f			| no overflow, good.
1061	| Overflow.  This means that the %d1 was 0xffffff00, so it
1062	| is now zero.  We will set the mantissa to reflect this, and
1063	| increment the exponent (checking for overflow there too)
1064	move.w	#0x8000,(%a0)
1065	addq.w	#1,-(%a0)
1066	cmp.w	#0x407f,(%a0)+		| exponent now overflown?
1067	jeq	fp_nsf_large		| yes, so make it infinity.
10689:	subq.l	#4,%a0
1069	printf	PNORM,"%p(",1,%a0
1070	printx	PNORM,%a0@
1071	printf	PNORM,")\n"
1072	rts
1073	| check nondefault rounding modes
10742:	subq.w	#2,%d2
1075	jcs	9b			| %d2 < 2, round to zero
1076	jhi	3f			| %d2 > 2, round to +infinity
1077	tst.b	(-3,%a0)		| to -inf
1078	jne	fp_nsf_doroundup	| negative, round to infinity
1079	jra	9b			| positive, round to zero
10803:	tst.b	(-3,%a0)		| to +inf
1081	jeq	fp_nsf_doroundup		| positive, round to infinity
1082	jra	9b			| negative, round to zero
1083	| Exponent overflow.  Just call it infinity.
1084fp_nsf_large:
1085	tst.b	(3,%a0)
1086	jeq	1f
1087	fp_set_sr FPSR_EXC_INEX2
10881:	fp_set_sr FPSR_EXC_OVFL
1089	move.w	(FPD_RND,FPDATA),%d2
1090	jne	3f			| %d2 = 0 round to nearest
10911:	move.w	#0x7fff,(-2,%a0)
1092	clr.l	(%a0)+
1093	clr.l	(%a0)
10942:	subq.l	#8,%a0
1095	printf	PNORM,"%p(",1,%a0
1096	printx	PNORM,%a0@
1097	printf	PNORM,")\n"
1098	rts
10993:	subq.w	#2,%d2
1100	jcs	5f			| %d2 < 2, round to zero
1101	jhi	4f			| %d2 > 2, round to +infinity
1102	tst.b	(-3,%a0)		| to -inf
1103	jne	1b
1104	jra	5f
11054:	tst.b	(-3,%a0)		| to +inf
1106	jeq	1b
11075:	move.w	#0x407e,(-2,%a0)
1108	move.l	#0xffffff00,(%a0)+
1109	clr.l	(%a0)
1110	jra	2b
1111	| Infinities or NaNs
1112fp_nsf_huge:
1113	subq.l	#4,%a0
1114	printf	PNORM,"%p(",1,%a0
1115	printx	PNORM,%a0@
1116	printf	PNORM,")\n"
1117	rts
1118
1119	| conv_ext2int (macro):
1120	| Generates a subroutine that converts an extended value to an
1121	| integer of a given size, again, with the appropriate type of
1122	| rounding.
1123
1124	| Macro arguments:
1125	| s:	size, as given in an assembly instruction.
1126	| b:	number of bits in that size.
1127
1128	| Subroutine arguments:
1129	| %a0:	source (struct fp_ext *)
1130
1131	| Returns the integer in %d0 (like it should)
1132
1133.macro conv_ext2int s,b
1134	.set	inf,(1<<(\b-1))-1	| i.e. MAXINT
1135	printf	PCONV,"e2i%d: %p(",2,#\b,%a0
1136	printx	PCONV,%a0@
1137	printf	PCONV,") "
1138	addq.l	#2,%a0
1139	move.w	(%a0)+,%d2		| exponent
1140	jeq	fp_e2i_zero\b		| zero / denorm (== 0, here)
1141	cmp.w	#0x7fff,%d2
1142	jeq	fp_e2i_huge\b		| Inf / NaN
1143	sub.w	#0x3ffe,%d2
1144	jcs	fp_e2i_small\b
1145	cmp.w	#\b,%d2
1146	jhi	fp_e2i_large\b
1147	move.l	(%a0),%d0
1148	move.l	%d0,%d1
1149	lsl.l	%d2,%d1
1150	jne	fp_e2i_round\b
1151	tst.l	(4,%a0)
1152	jne	fp_e2i_round\b
1153	neg.w	%d2
1154	add.w	#32,%d2
1155	lsr.l	%d2,%d0
11569:	tst.w	(-4,%a0)
1157	jne	1f
1158	tst.\s	%d0
1159	jmi	fp_e2i_large\b
1160	printf	PCONV,"-> %p\n",1,%d0
1161	rts
11621:	neg.\s	%d0
1163	jeq	1f
1164	jpl	fp_e2i_large\b
11651:	printf	PCONV,"-> %p\n",1,%d0
1166	rts
1167fp_e2i_round\b:
1168	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
1169	neg.w	%d2
1170	add.w	#32,%d2
1171	.if	\b>16
1172	jeq	5f
1173	.endif
1174	lsr.l	%d2,%d0
1175	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1176	jne	2f			| %d2 == 0, round to nearest
1177	tst.l	%d1			| test guard bit
1178	jpl	9b			| zero is closer
1179	btst	%d2,%d0			| test lsb bit (%d2 still 0)
1180	jne	fp_e2i_doroundup\b
1181	lsl.l	#1,%d1			| check low bits
1182	jne	fp_e2i_doroundup\b
1183	tst.l	(4,%a0)
1184	jeq	9b
1185fp_e2i_doroundup\b:
1186	addq.l	#1,%d0
1187	jra	9b
1188	| check nondefault rounding modes
11892:	subq.w	#2,%d2
1190	jcs	9b			| %d2 < 2, round to zero
1191	jhi	3f			| %d2 > 2, round to +infinity
1192	tst.w	(-4,%a0)		| to -inf
1193	jne	fp_e2i_doroundup\b	| negative, round to infinity
1194	jra	9b			| positive, round to zero
11953:	tst.w	(-4,%a0)		| to +inf
1196	jeq	fp_e2i_doroundup\b	| positive, round to infinity
1197	jra	9b	| negative, round to zero
1198	| we are only want -2**127 get correctly rounded here,
1199	| since the guard bit is in the lower lword.
1200	| everything else ends up anyway as overflow.
1201	.if	\b>16
12025:	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1203	jne	2b			| %d2 == 0, round to nearest
1204	move.l	(4,%a0),%d1		| test guard bit
1205	jpl	9b			| zero is closer
1206	lsl.l	#1,%d1			| check low bits
1207	jne	fp_e2i_doroundup\b
1208	jra	9b
1209	.endif
1210fp_e2i_zero\b:
1211	clr.l	%d0
1212	tst.l	(%a0)+
1213	jne	1f
1214	tst.l	(%a0)
1215	jeq	3f
12161:	subq.l	#4,%a0
1217	fp_clr_sr FPSR_EXC_UNFL		| fp_normalize_ext has set this bit
1218fp_e2i_small\b:
1219	fp_set_sr FPSR_EXC_INEX2
1220	clr.l	%d0
1221	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1222	subq.w	#2,%d2
1223	jcs	3f			| %d2 < 2, round to nearest/zero
1224	jhi	2f			| %d2 > 2, round to +infinity
1225	tst.w	(-4,%a0)		| to -inf
1226	jeq	3f
1227	subq.\s	#1,%d0
1228	jra	3f
12292:	tst.w	(-4,%a0)		| to +inf
1230	jne	3f
1231	addq.\s	#1,%d0
12323:	printf	PCONV,"-> %p\n",1,%d0
1233	rts
1234fp_e2i_large\b:
1235	fp_set_sr FPSR_EXC_OPERR
1236	move.\s	#inf,%d0
1237	tst.w	(-4,%a0)
1238	jeq	1f
1239	addq.\s	#1,%d0
12401:	printf	PCONV,"-> %p\n",1,%d0
1241	rts
1242fp_e2i_huge\b:
1243	move.\s	(%a0),%d0
1244	tst.l	(%a0)
1245	jne	1f
1246	tst.l	(%a0)
1247	jeq	fp_e2i_large\b
1248	| fp_normalize_ext has set this bit already
1249	| and made the number nonsignaling
12501:	fp_tst_sr FPSR_EXC_SNAN
1251	jne	1f
1252	fp_set_sr FPSR_EXC_OPERR
12531:	printf	PCONV,"-> %p\n",1,%d0
1254	rts
1255.endm
1256
1257fp_conv_ext2long:
1258	conv_ext2int l,32
1259
1260fp_conv_ext2short:
1261	conv_ext2int w,16
1262
1263fp_conv_ext2byte:
1264	conv_ext2int b,8
1265
1266fp_conv_ext2double:
1267	jsr	fp_normalize_double
1268	printf	PCONV,"e2d: %p(",1,%a0
1269	printx	PCONV,%a0@
1270	printf	PCONV,"), "
1271	move.l	(%a0)+,%d2
1272	cmp.w	#0x7fff,%d2
1273	jne	1f
1274	move.w	#0x7ff,%d2
1275	move.l	(%a0)+,%d0
1276	jra	2f
12771:	sub.w	#0x3fff-0x3ff,%d2
1278	move.l	(%a0)+,%d0
1279	jmi	2f
1280	clr.w	%d2
12812:	lsl.w	#5,%d2
1282	lsl.l	#7,%d2
1283	lsl.l	#8,%d2
1284	move.l	%d0,%d1
1285	lsl.l	#1,%d0
1286	lsr.l	#4,%d0
1287	lsr.l	#8,%d0
1288	or.l	%d2,%d0
1289	putuser.l %d0,(%a1)+,fp_err_ua2,%a1
1290	moveq	#21,%d0
1291	lsl.l	%d0,%d1
1292	move.l	(%a0),%d0
1293	lsr.l	#4,%d0
1294	lsr.l	#7,%d0
1295	or.l	%d1,%d0
1296	putuser.l %d0,(%a1),fp_err_ua2,%a1
1297#ifdef FPU_EMU_DEBUG
1298	getuser.l %a1@(-4),%d0,fp_err_ua2,%a1
1299	getuser.l %a1@(0),%d1,fp_err_ua2,%a1
1300	printf	PCONV,"%p(%08x%08x)\n",3,%a1,%d0,%d1
1301#endif
1302	rts
1303
1304fp_conv_ext2single:
1305	jsr	fp_normalize_single
1306	printf	PCONV,"e2s: %p(",1,%a0
1307	printx	PCONV,%a0@
1308	printf	PCONV,"), "
1309	move.l	(%a0)+,%d1
1310	cmp.w	#0x7fff,%d1
1311	jne	1f
1312	move.w	#0xff,%d1
1313	move.l	(%a0)+,%d0
1314	jra	2f
13151:	sub.w	#0x3fff-0x7f,%d1
1316	move.l	(%a0)+,%d0
1317	jmi	2f
1318	clr.w	%d1
13192:	lsl.w	#8,%d1
1320	lsl.l	#7,%d1
1321	lsl.l	#8,%d1
1322	bclr	#31,%d0
1323	lsr.l	#8,%d0
1324	or.l	%d1,%d0
1325	printf	PCONV,"%08x\n",1,%d0
1326	rts
1327
1328	| special return addresses for instr that
1329	| encode the rounding precision in the opcode
1330	| (e.g. fsmove,fdmove)
1331
1332fp_finalrounding_single:
1333	addq.l	#8,%sp
1334	jsr	fp_normalize_ext
1335	jsr	fp_normalize_single
1336	jra	fp_finaltest
1337
1338fp_finalrounding_single_fast:
1339	addq.l	#8,%sp
1340	jsr	fp_normalize_ext
1341	jsr	fp_normalize_single_fast
1342	jra	fp_finaltest
1343
1344fp_finalrounding_double:
1345	addq.l	#8,%sp
1346	jsr	fp_normalize_ext
1347	jsr	fp_normalize_double
1348	jra	fp_finaltest
1349
1350	| fp_finaltest:
1351	| set the emulated status register based on the outcome of an
1352	| emulated instruction.
1353
1354fp_finalrounding:
1355	addq.l	#8,%sp
1356|	printf	,"f: %p\n",1,%a0
1357	jsr	fp_normalize_ext
1358	move.w	(FPD_PREC,FPDATA),%d0
1359	subq.w	#1,%d0
1360	jcs	fp_finaltest
1361	jne	1f
1362	jsr	fp_normalize_single
1363	jra	2f
13641:	jsr	fp_normalize_double
13652:|	printf	,"f: %p\n",1,%a0
1366fp_finaltest:
1367	| First, we do some of the obvious tests for the exception
1368	| status byte and condition code bytes of fp_sr here, so that
1369	| they do not have to be handled individually by every
1370	| emulated instruction.
1371	clr.l	%d0
1372	addq.l	#1,%a0
1373	tst.b	(%a0)+			| sign
1374	jeq	1f
1375	bset	#FPSR_CC_NEG-24,%d0	| N bit
13761:	cmp.w	#0x7fff,(%a0)+		| exponent
1377	jeq	2f
1378	| test for zero
1379	moveq	#FPSR_CC_Z-24,%d1
1380	tst.l	(%a0)+
1381	jne	9f
1382	tst.l	(%a0)
1383	jne	9f
1384	jra	8f
1385	| infinitiv and NAN
13862:	moveq	#FPSR_CC_NAN-24,%d1
1387	move.l	(%a0)+,%d2
1388	lsl.l	#1,%d2			| ignore high bit
1389	jne	8f
1390	tst.l	(%a0)
1391	jne	8f
1392	moveq	#FPSR_CC_INF-24,%d1
13938:	bset	%d1,%d0
13949:	move.b	%d0,(FPD_FPSR+0,FPDATA)	| set condition test result
1395	| move instructions enter here
1396	| Here, we test things in the exception status byte, and set
1397	| other things in the accrued exception byte accordingly.
1398	| Emulated instructions can set various things in the former,
1399	| as defined in fp_emu.h.
1400fp_final:
1401	move.l	(FPD_FPSR,FPDATA),%d0
1402#if 0
1403	btst	#FPSR_EXC_SNAN,%d0	| EXC_SNAN
1404	jne	1f
1405	btst	#FPSR_EXC_OPERR,%d0	| EXC_OPERR
1406	jeq	2f
14071:	bset	#FPSR_AEXC_IOP,%d0	| set IOP bit
14082:	btst	#FPSR_EXC_OVFL,%d0	| EXC_OVFL
1409	jeq	1f
1410	bset	#FPSR_AEXC_OVFL,%d0	| set OVFL bit
14111:	btst	#FPSR_EXC_UNFL,%d0	| EXC_UNFL
1412	jeq	1f
1413	btst	#FPSR_EXC_INEX2,%d0	| EXC_INEX2
1414	jeq	1f
1415	bset	#FPSR_AEXC_UNFL,%d0	| set UNFL bit
14161:	btst	#FPSR_EXC_DZ,%d0	| EXC_INEX1
1417	jeq	1f
1418	bset	#FPSR_AEXC_DZ,%d0	| set DZ bit
14191:	btst	#FPSR_EXC_OVFL,%d0	| EXC_OVFL
1420	jne	1f
1421	btst	#FPSR_EXC_INEX2,%d0	| EXC_INEX2
1422	jne	1f
1423	btst	#FPSR_EXC_INEX1,%d0	| EXC_INEX1
1424	jeq	2f
14251:	bset	#FPSR_AEXC_INEX,%d0	| set INEX bit
14262:	move.l	%d0,(FPD_FPSR,FPDATA)
1427#else
1428	| same as above, greatly optimized, but untested (yet)
1429	move.l	%d0,%d2
1430	lsr.l	#5,%d0
1431	move.l	%d0,%d1
1432	lsr.l	#4,%d1
1433	or.l	%d0,%d1
1434	and.b	#0x08,%d1
1435	move.l	%d2,%d0
1436	lsr.l	#6,%d0
1437	or.l	%d1,%d0
1438	move.l	%d2,%d1
1439	lsr.l	#4,%d1
1440	or.b	#0xdf,%d1
1441	and.b	%d1,%d0
1442	move.l	%d2,%d1
1443	lsr.l	#7,%d1
1444	and.b	#0x80,%d1
1445	or.b	%d1,%d0
1446	and.b	#0xf8,%d0
1447	or.b	%d0,%d2
1448	move.l	%d2,(FPD_FPSR,FPDATA)
1449#endif
1450	move.b	(FPD_FPSR+2,FPDATA),%d0
1451	and.b	(FPD_FPCR+2,FPDATA),%d0
1452	jeq	1f
1453	printf	,"send signal!!!\n"
14541:	jra	fp_end
v5.14.15
   1/*
   2 * fp_util.S
   3 *
   4 * Copyright Roman Zippel, 1997.  All rights reserved.
   5 *
   6 * Redistribution and use in source and binary forms, with or without
   7 * modification, are permitted provided that the following conditions
   8 * are met:
   9 * 1. Redistributions of source code must retain the above copyright
  10 *    notice, and the entire permission notice in its entirety,
  11 *    including the disclaimer of warranties.
  12 * 2. Redistributions in binary form must reproduce the above copyright
  13 *    notice, this list of conditions and the following disclaimer in the
  14 *    documentation and/or other materials provided with the distribution.
  15 * 3. The name of the author may not be used to endorse or promote
  16 *    products derived from this software without specific prior
  17 *    written permission.
  18 *
  19 * ALTERNATIVELY, this product may be distributed under the terms of
  20 * the GNU General Public License, in which case the provisions of the GPL are
  21 * required INSTEAD OF the above restrictions.  (This clause is
  22 * necessary due to a potential bad interaction between the GPL and
  23 * the restrictions contained in a BSD-style copyright.)
  24 *
  25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  35 * OF THE POSSIBILITY OF SUCH DAMAGE.
  36 */
  37
  38#include "fp_emu.h"
  39
  40/*
  41 * Here are lots of conversion and normalization functions mainly
  42 * used by fp_scan.S
  43 * Note that these functions are optimized for "normal" numbers,
  44 * these are handled first and exit as fast as possible, this is
  45 * especially important for fp_normalize_ext/fp_conv_ext2ext, as
  46 * it's called very often.
  47 * The register usage is optimized for fp_scan.S and which register
  48 * is currently at that time unused, be careful if you want change
  49 * something here. %d0 and %d1 is always usable, sometimes %d2 (or
  50 * only the lower half) most function have to return the %a0
  51 * unmodified, so that the caller can immediately reuse it.
  52 */
  53
  54	.globl	fp_ill, fp_end
  55
  56	| exits from fp_scan:
  57	| illegal instruction
  58fp_ill:
  59	printf	,"fp_illegal\n"
  60	rts
  61	| completed instruction
  62fp_end:
  63	tst.l	(TASK_MM-8,%a2)
  64	jmi	1f
  65	tst.l	(TASK_MM-4,%a2)
  66	jmi	1f
  67	tst.l	(TASK_MM,%a2)
  68	jpl	2f
  691:	printf	,"oops:%p,%p,%p\n",3,%a2@(TASK_MM-8),%a2@(TASK_MM-4),%a2@(TASK_MM)
  702:	clr.l	%d0
  71	rts
  72
  73	.globl	fp_conv_long2ext, fp_conv_single2ext
  74	.globl	fp_conv_double2ext, fp_conv_ext2ext
  75	.globl	fp_normalize_ext, fp_normalize_double
  76	.globl	fp_normalize_single, fp_normalize_single_fast
  77	.globl	fp_conv_ext2double, fp_conv_ext2single
  78	.globl	fp_conv_ext2long, fp_conv_ext2short
  79	.globl	fp_conv_ext2byte
  80	.globl	fp_finalrounding_single, fp_finalrounding_single_fast
  81	.globl	fp_finalrounding_double
  82	.globl	fp_finalrounding, fp_finaltest, fp_final
  83
  84/*
  85 * First several conversion functions from a source operand
  86 * into the extended format. Note, that only fp_conv_ext2ext
  87 * normalizes the number and is always called after the other
  88 * conversion functions, which only move the information into
  89 * fp_ext structure.
  90 */
  91
  92	| fp_conv_long2ext:
  93	|
  94	| args:	%d0 = source (32-bit long)
  95	|	%a0 = destination (ptr to struct fp_ext)
  96
  97fp_conv_long2ext:
  98	printf	PCONV,"l2e: %p -> %p(",2,%d0,%a0
  99	clr.l	%d1			| sign defaults to zero
 100	tst.l	%d0
 101	jeq	fp_l2e_zero		| is source zero?
 102	jpl	1f			| positive?
 103	moveq	#1,%d1
 104	neg.l	%d0
 1051:	swap	%d1
 106	move.w	#0x3fff+31,%d1
 107	move.l	%d1,(%a0)+		| set sign / exp
 108	move.l	%d0,(%a0)+		| set mantissa
 109	clr.l	(%a0)
 110	subq.l	#8,%a0			| restore %a0
 111	printx	PCONV,%a0@
 112	printf	PCONV,")\n"
 113	rts
 114	| source is zero
 115fp_l2e_zero:
 116	clr.l	(%a0)+
 117	clr.l	(%a0)+
 118	clr.l	(%a0)
 119	subq.l	#8,%a0
 120	printx	PCONV,%a0@
 121	printf	PCONV,")\n"
 122	rts
 123
 124	| fp_conv_single2ext
 125	| args:	%d0 = source (single-precision fp value)
 126	|	%a0 = dest (struct fp_ext *)
 127
 128fp_conv_single2ext:
 129	printf	PCONV,"s2e: %p -> %p(",2,%d0,%a0
 130	move.l	%d0,%d1
 131	lsl.l	#8,%d0			| shift mantissa
 132	lsr.l	#8,%d1			| exponent / sign
 133	lsr.l	#7,%d1
 134	lsr.w	#8,%d1
 135	jeq	fp_s2e_small		| zero / denormal?
 136	cmp.w	#0xff,%d1		| NaN / Inf?
 137	jeq	fp_s2e_large
 138	bset	#31,%d0			| set explizit bit
 139	add.w	#0x3fff-0x7f,%d1	| re-bias the exponent.
 1409:	move.l	%d1,(%a0)+		| fp_ext.sign, fp_ext.exp
 141	move.l	%d0,(%a0)+		| high lword of fp_ext.mant
 142	clr.l	(%a0)			| low lword = 0
 143	subq.l	#8,%a0
 144	printx	PCONV,%a0@
 145	printf	PCONV,")\n"
 146	rts
 147	| zeros and denormalized
 148fp_s2e_small:
 149	| exponent is zero, so explizit bit is already zero too
 150	tst.l	%d0
 151	jeq	9b
 152	move.w	#0x4000-0x7f,%d1
 153	jra	9b
 154	| infinities and NAN
 155fp_s2e_large:
 156	bclr	#31,%d0			| clear explizit bit
 157	move.w	#0x7fff,%d1
 158	jra	9b
 159
 160fp_conv_double2ext:
 161#ifdef FPU_EMU_DEBUG
 162	getuser.l %a1@(0),%d0,fp_err_ua2,%a1
 163	getuser.l %a1@(4),%d1,fp_err_ua2,%a1
 164	printf	PCONV,"d2e: %p%p -> %p(",3,%d0,%d1,%a0
 165#endif
 166	getuser.l (%a1)+,%d0,fp_err_ua2,%a1
 167	move.l	%d0,%d1
 168	lsl.l	#8,%d0			| shift high mantissa
 169	lsl.l	#3,%d0
 170	lsr.l	#8,%d1			| exponent / sign
 171	lsr.l	#7,%d1
 172	lsr.w	#5,%d1
 173	jeq	fp_d2e_small		| zero / denormal?
 174	cmp.w	#0x7ff,%d1		| NaN / Inf?
 175	jeq	fp_d2e_large
 176	bset	#31,%d0			| set explizit bit
 177	add.w	#0x3fff-0x3ff,%d1	| re-bias the exponent.
 1789:	move.l	%d1,(%a0)+		| fp_ext.sign, fp_ext.exp
 179	move.l	%d0,(%a0)+
 180	getuser.l (%a1)+,%d0,fp_err_ua2,%a1
 181	move.l	%d0,%d1
 182	lsl.l	#8,%d0
 183	lsl.l	#3,%d0
 184	move.l	%d0,(%a0)
 185	moveq	#21,%d0
 186	lsr.l	%d0,%d1
 187	or.l	%d1,-(%a0)
 188	subq.l	#4,%a0
 189	printx	PCONV,%a0@
 190	printf	PCONV,")\n"
 191	rts
 192	| zeros and denormalized
 193fp_d2e_small:
 194	| exponent is zero, so explizit bit is already zero too
 195	tst.l	%d0
 196	jeq	9b
 197	move.w	#0x4000-0x3ff,%d1
 198	jra	9b
 199	| infinities and NAN
 200fp_d2e_large:
 201	bclr	#31,%d0			| clear explizit bit
 202	move.w	#0x7fff,%d1
 203	jra	9b
 204
 205	| fp_conv_ext2ext:
 206	| originally used to get longdouble from userspace, now it's
 207	| called before arithmetic operations to make sure the number
 208	| is normalized [maybe rename it?].
 209	| args:	%a0 = dest (struct fp_ext *)
 210	| returns 0 in %d0 for a NaN, otherwise 1
 211
 212fp_conv_ext2ext:
 213	printf	PCONV,"e2e: %p(",1,%a0
 214	printx	PCONV,%a0@
 215	printf	PCONV,"), "
 216	move.l	(%a0)+,%d0
 217	cmp.w	#0x7fff,%d0		| Inf / NaN?
 218	jeq	fp_e2e_large
 219	move.l	(%a0),%d0
 220	jpl	fp_e2e_small		| zero / denorm?
 221	| The high bit is set, so normalization is irrelevant.
 222fp_e2e_checkround:
 223	subq.l	#4,%a0
 224#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 225	move.b	(%a0),%d0
 226	jne	fp_e2e_round
 227#endif
 228	printf	PCONV,"%p(",1,%a0
 229	printx	PCONV,%a0@
 230	printf	PCONV,")\n"
 231	moveq	#1,%d0
 232	rts
 233#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 234fp_e2e_round:
 235	fp_set_sr FPSR_EXC_INEX2
 236	clr.b	(%a0)
 237	move.w	(FPD_RND,FPDATA),%d2
 238	jne	fp_e2e_roundother	| %d2 == 0, round to nearest
 239	tst.b	%d0			| test guard bit
 240	jpl	9f			| zero is closer
 241	btst	#0,(11,%a0)		| test lsb bit
 242	jne	fp_e2e_doroundup	| round to infinity
 243	lsl.b	#1,%d0			| check low bits
 244	jeq	9f			| round to zero
 245fp_e2e_doroundup:
 246	addq.l	#1,(8,%a0)
 247	jcc	9f
 248	addq.l	#1,(4,%a0)
 249	jcc	9f
 250	move.w	#0x8000,(4,%a0)
 251	addq.w	#1,(2,%a0)
 2529:	printf	PNORM,"%p(",1,%a0
 253	printx	PNORM,%a0@
 254	printf	PNORM,")\n"
 255	rts
 256fp_e2e_roundother:
 257	subq.w	#2,%d2
 258	jcs	9b			| %d2 < 2, round to zero
 259	jhi	1f			| %d2 > 2, round to +infinity
 260	tst.b	(1,%a0)			| to -inf
 261	jne	fp_e2e_doroundup	| negative, round to infinity
 262	jra	9b			| positive, round to zero
 2631:	tst.b	(1,%a0)			| to +inf
 264	jeq	fp_e2e_doroundup	| positive, round to infinity
 265	jra	9b			| negative, round to zero
 266#endif
 267	| zeros and subnormals:
 268	| try to normalize these anyway.
 269fp_e2e_small:
 270	jne	fp_e2e_small1		| high lword zero?
 271	move.l	(4,%a0),%d0
 272	jne	fp_e2e_small2
 273#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 274	clr.l	%d0
 275	move.b	(-4,%a0),%d0
 276	jne	fp_e2e_small3
 277#endif
 278	| Genuine zero.
 279	clr.w	-(%a0)
 280	subq.l	#2,%a0
 281	printf	PNORM,"%p(",1,%a0
 282	printx	PNORM,%a0@
 283	printf	PNORM,")\n"
 284	moveq	#1,%d0
 285	rts
 286	| definitely subnormal, need to shift all 64 bits
 287fp_e2e_small1:
 288	bfffo	%d0{#0,#32},%d1
 289	move.w	-(%a0),%d2
 290	sub.w	%d1,%d2
 291	jcc	1f
 292	| Pathologically small, denormalize.
 293	add.w	%d2,%d1
 294	clr.w	%d2
 2951:	move.w	%d2,(%a0)+
 296	move.w	%d1,%d2
 297	jeq	fp_e2e_checkround
 298	| fancy 64-bit double-shift begins here
 299	lsl.l	%d2,%d0
 300	move.l	%d0,(%a0)+
 301	move.l	(%a0),%d0
 302	move.l	%d0,%d1
 303	lsl.l	%d2,%d0
 304	move.l	%d0,(%a0)
 305	neg.w	%d2
 306	and.w	#0x1f,%d2
 307	lsr.l	%d2,%d1
 308	or.l	%d1,-(%a0)
 309#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 310fp_e2e_extra1:
 311	clr.l	%d0
 312	move.b	(-4,%a0),%d0
 313	neg.w	%d2
 314	add.w	#24,%d2
 315	jcc	1f
 316	clr.b	(-4,%a0)
 317	lsl.l	%d2,%d0
 318	or.l	%d0,(4,%a0)
 319	jra	fp_e2e_checkround
 3201:	addq.w	#8,%d2
 321	lsl.l	%d2,%d0
 322	move.b	%d0,(-4,%a0)
 323	lsr.l	#8,%d0
 324	or.l	%d0,(4,%a0)
 325#endif
 326	jra	fp_e2e_checkround
 327	| pathologically small subnormal
 328fp_e2e_small2:
 329	bfffo	%d0{#0,#32},%d1
 330	add.w	#32,%d1
 331	move.w	-(%a0),%d2
 332	sub.w	%d1,%d2
 333	jcc	1f
 334	| Beyond pathologically small, denormalize.
 335	add.w	%d2,%d1
 336	clr.w	%d2
 3371:	move.w	%d2,(%a0)+
 338	ext.l	%d1
 339	jeq	fp_e2e_checkround
 340	clr.l	(4,%a0)
 341	sub.w	#32,%d2
 342	jcs	1f
 343	lsl.l	%d1,%d0			| lower lword needs only to be shifted
 344	move.l	%d0,(%a0)		| into the higher lword
 345#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 346	clr.l	%d0
 347	move.b	(-4,%a0),%d0
 348	clr.b	(-4,%a0)
 349	neg.w	%d1
 350	add.w	#32,%d1
 351	bfins	%d0,(%a0){%d1,#8}
 352#endif
 353	jra	fp_e2e_checkround
 3541:	neg.w	%d1			| lower lword is splitted between
 355	bfins	%d0,(%a0){%d1,#32}	| higher and lower lword
 356#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
 357	jra	fp_e2e_checkround
 358#else
 359	move.w	%d1,%d2
 360	jra	fp_e2e_extra1
 361	| These are extremely small numbers, that will mostly end up as zero
 362	| anyway, so this is only important for correct rounding.
 363fp_e2e_small3:
 364	bfffo	%d0{#24,#8},%d1
 365	add.w	#40,%d1
 366	move.w	-(%a0),%d2
 367	sub.w	%d1,%d2
 368	jcc	1f
 369	| Pathologically small, denormalize.
 370	add.w	%d2,%d1
 371	clr.w	%d2
 3721:	move.w	%d2,(%a0)+
 373	ext.l	%d1
 374	jeq	fp_e2e_checkround
 375	cmp.w	#8,%d1
 376	jcs	2f
 3771:	clr.b	(-4,%a0)
 378	sub.w	#64,%d1
 379	jcs	1f
 380	add.w	#24,%d1
 381	lsl.l	%d1,%d0
 382	move.l	%d0,(%a0)
 383	jra	fp_e2e_checkround
 3841:	neg.w	%d1
 385	bfins	%d0,(%a0){%d1,#8}
 386	jra	fp_e2e_checkround
 3872:	lsl.l	%d1,%d0
 388	move.b	%d0,(-4,%a0)
 389	lsr.l	#8,%d0
 390	move.b	%d0,(7,%a0)
 391	jra	fp_e2e_checkround
 392#endif
 3931:	move.l	%d0,%d1			| lower lword is splitted between
 394	lsl.l	%d2,%d0			| higher and lower lword
 395	move.l	%d0,(%a0)
 396	move.l	%d1,%d0
 397	neg.w	%d2
 398	add.w	#32,%d2
 399	lsr.l	%d2,%d0
 400	move.l	%d0,-(%a0)
 401	jra	fp_e2e_checkround
 402	| Infinities and NaNs
 403fp_e2e_large:
 404	move.l	(%a0)+,%d0
 405	jne	3f
 4061:	tst.l	(%a0)
 407	jne	4f
 408	moveq	#1,%d0
 4092:	subq.l	#8,%a0
 410	printf	PCONV,"%p(",1,%a0
 411	printx	PCONV,%a0@
 412	printf	PCONV,")\n"
 413	rts
 414	| we have maybe a NaN, shift off the highest bit
 4153:	lsl.l	#1,%d0
 416	jeq	1b
 417	| we have a NaN, clear the return value
 4184:	clrl	%d0
 419	jra	2b
 420
 421
 422/*
 423 * Normalization functions.  Call these on the output of general
 424 * FP operators, and before any conversion into the destination
 425 * formats. fp_normalize_ext has always to be called first, the
 426 * following conversion functions expect an already normalized
 427 * number.
 428 */
 429
 430	| fp_normalize_ext:
 431	| normalize an extended in extended (unpacked) format, basically
 432	| it does the same as fp_conv_ext2ext, additionally it also does
 433	| the necessary postprocessing checks.
 434	| args:	%a0 (struct fp_ext *)
 435	| NOTE: it does _not_ modify %a0/%a1 and the upper word of %d2
 436
 437fp_normalize_ext:
 438	printf	PNORM,"ne: %p(",1,%a0
 439	printx	PNORM,%a0@
 440	printf	PNORM,"), "
 441	move.l	(%a0)+,%d0
 442	cmp.w	#0x7fff,%d0		| Inf / NaN?
 443	jeq	fp_ne_large
 444	move.l	(%a0),%d0
 445	jpl	fp_ne_small		| zero / denorm?
 446	| The high bit is set, so normalization is irrelevant.
 447fp_ne_checkround:
 448	subq.l	#4,%a0
 449#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 450	move.b	(%a0),%d0
 451	jne	fp_ne_round
 452#endif
 453	printf	PNORM,"%p(",1,%a0
 454	printx	PNORM,%a0@
 455	printf	PNORM,")\n"
 456	rts
 457#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 458fp_ne_round:
 459	fp_set_sr FPSR_EXC_INEX2
 460	clr.b	(%a0)
 461	move.w	(FPD_RND,FPDATA),%d2
 462	jne	fp_ne_roundother	| %d2 == 0, round to nearest
 463	tst.b	%d0			| test guard bit
 464	jpl	9f			| zero is closer
 465	btst	#0,(11,%a0)		| test lsb bit
 466	jne	fp_ne_doroundup		| round to infinity
 467	lsl.b	#1,%d0			| check low bits
 468	jeq	9f			| round to zero
 469fp_ne_doroundup:
 470	addq.l	#1,(8,%a0)
 471	jcc	9f
 472	addq.l	#1,(4,%a0)
 473	jcc	9f
 474	addq.w	#1,(2,%a0)
 475	move.w	#0x8000,(4,%a0)
 4769:	printf	PNORM,"%p(",1,%a0
 477	printx	PNORM,%a0@
 478	printf	PNORM,")\n"
 479	rts
 480fp_ne_roundother:
 481	subq.w	#2,%d2
 482	jcs	9b			| %d2 < 2, round to zero
 483	jhi	1f			| %d2 > 2, round to +infinity
 484	tst.b	(1,%a0)			| to -inf
 485	jne	fp_ne_doroundup		| negative, round to infinity
 486	jra	9b			| positive, round to zero
 4871:	tst.b	(1,%a0)			| to +inf
 488	jeq	fp_ne_doroundup		| positive, round to infinity
 489	jra	9b			| negative, round to zero
 490#endif
 491	| Zeros and subnormal numbers
 492	| These are probably merely subnormal, rather than "denormalized"
 493	|  numbers, so we will try to make them normal again.
 494fp_ne_small:
 495	jne	fp_ne_small1		| high lword zero?
 496	move.l	(4,%a0),%d0
 497	jne	fp_ne_small2
 498#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 499	clr.l	%d0
 500	move.b	(-4,%a0),%d0
 501	jne	fp_ne_small3
 502#endif
 503	| Genuine zero.
 504	clr.w	-(%a0)
 505	subq.l	#2,%a0
 506	printf	PNORM,"%p(",1,%a0
 507	printx	PNORM,%a0@
 508	printf	PNORM,")\n"
 509	rts
 510	| Subnormal.
 511fp_ne_small1:
 512	bfffo	%d0{#0,#32},%d1
 513	move.w	-(%a0),%d2
 514	sub.w	%d1,%d2
 515	jcc	1f
 516	| Pathologically small, denormalize.
 517	add.w	%d2,%d1
 518	clr.w	%d2
 519	fp_set_sr FPSR_EXC_UNFL
 5201:	move.w	%d2,(%a0)+
 521	move.w	%d1,%d2
 522	jeq	fp_ne_checkround
 523	| This is exactly the same 64-bit double shift as seen above.
 524	lsl.l	%d2,%d0
 525	move.l	%d0,(%a0)+
 526	move.l	(%a0),%d0
 527	move.l	%d0,%d1
 528	lsl.l	%d2,%d0
 529	move.l	%d0,(%a0)
 530	neg.w	%d2
 531	and.w	#0x1f,%d2
 532	lsr.l	%d2,%d1
 533	or.l	%d1,-(%a0)
 534#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 535fp_ne_extra1:
 536	clr.l	%d0
 537	move.b	(-4,%a0),%d0
 538	neg.w	%d2
 539	add.w	#24,%d2
 540	jcc	1f
 541	clr.b	(-4,%a0)
 542	lsl.l	%d2,%d0
 543	or.l	%d0,(4,%a0)
 544	jra	fp_ne_checkround
 5451:	addq.w	#8,%d2
 546	lsl.l	%d2,%d0
 547	move.b	%d0,(-4,%a0)
 548	lsr.l	#8,%d0
 549	or.l	%d0,(4,%a0)
 550#endif
 551	jra	fp_ne_checkround
 552	| May or may not be subnormal, if so, only 32 bits to shift.
 553fp_ne_small2:
 554	bfffo	%d0{#0,#32},%d1
 555	add.w	#32,%d1
 556	move.w	-(%a0),%d2
 557	sub.w	%d1,%d2
 558	jcc	1f
 559	| Beyond pathologically small, denormalize.
 560	add.w	%d2,%d1
 561	clr.w	%d2
 562	fp_set_sr FPSR_EXC_UNFL
 5631:	move.w	%d2,(%a0)+
 564	ext.l	%d1
 565	jeq	fp_ne_checkround
 566	clr.l	(4,%a0)
 567	sub.w	#32,%d1
 568	jcs	1f
 569	lsl.l	%d1,%d0			| lower lword needs only to be shifted
 570	move.l	%d0,(%a0)		| into the higher lword
 571#ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
 572	clr.l	%d0
 573	move.b	(-4,%a0),%d0
 574	clr.b	(-4,%a0)
 575	neg.w	%d1
 576	add.w	#32,%d1
 577	bfins	%d0,(%a0){%d1,#8}
 578#endif
 579	jra	fp_ne_checkround
 5801:	neg.w	%d1			| lower lword is splitted between
 581	bfins	%d0,(%a0){%d1,#32}	| higher and lower lword
 582#ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
 583	jra	fp_ne_checkround
 584#else
 585	move.w	%d1,%d2
 586	jra	fp_ne_extra1
 587	| These are extremely small numbers, that will mostly end up as zero
 588	| anyway, so this is only important for correct rounding.
 589fp_ne_small3:
 590	bfffo	%d0{#24,#8},%d1
 591	add.w	#40,%d1
 592	move.w	-(%a0),%d2
 593	sub.w	%d1,%d2
 594	jcc	1f
 595	| Pathologically small, denormalize.
 596	add.w	%d2,%d1
 597	clr.w	%d2
 5981:	move.w	%d2,(%a0)+
 599	ext.l	%d1
 600	jeq	fp_ne_checkround
 601	cmp.w	#8,%d1
 602	jcs	2f
 6031:	clr.b	(-4,%a0)
 604	sub.w	#64,%d1
 605	jcs	1f
 606	add.w	#24,%d1
 607	lsl.l	%d1,%d0
 608	move.l	%d0,(%a0)
 609	jra	fp_ne_checkround
 6101:	neg.w	%d1
 611	bfins	%d0,(%a0){%d1,#8}
 612	jra	fp_ne_checkround
 6132:	lsl.l	%d1,%d0
 614	move.b	%d0,(-4,%a0)
 615	lsr.l	#8,%d0
 616	move.b	%d0,(7,%a0)
 617	jra	fp_ne_checkround
 618#endif
 619	| Infinities and NaNs, again, same as above.
 620fp_ne_large:
 621	move.l	(%a0)+,%d0
 622	jne	3f
 6231:	tst.l	(%a0)
 624	jne	4f
 6252:	subq.l	#8,%a0
 626	printf	PNORM,"%p(",1,%a0
 627	printx	PNORM,%a0@
 628	printf	PNORM,")\n"
 629	rts
 630	| we have maybe a NaN, shift off the highest bit
 6313:	move.l	%d0,%d1
 632	lsl.l	#1,%d1
 633	jne	4f
 634	clr.l	(-4,%a0)
 635	jra	1b
 636	| we have a NaN, test if it is signaling
 6374:	bset	#30,%d0
 638	jne	2b
 639	fp_set_sr FPSR_EXC_SNAN
 640	move.l	%d0,(-4,%a0)
 641	jra	2b
 642
 643	| these next two do rounding as per the IEEE standard.
 644	| values for the rounding modes appear to be:
 645	| 0:	Round to nearest
 646	| 1:	Round to zero
 647	| 2:	Round to -Infinity
 648	| 3:	Round to +Infinity
 649	| both functions expect that fp_normalize was already
 650	| called (and extended argument is already normalized
 651	| as far as possible), these are used if there is different
 652	| rounding precision is selected and before converting
 653	| into single/double
 654
 655	| fp_normalize_double:
 656	| normalize an extended with double (52-bit) precision
 657	| args:	 %a0 (struct fp_ext *)
 658
 659fp_normalize_double:
 660	printf	PNORM,"nd: %p(",1,%a0
 661	printx	PNORM,%a0@
 662	printf	PNORM,"), "
 663	move.l	(%a0)+,%d2
 664	tst.w	%d2
 665	jeq	fp_nd_zero		| zero / denormalized
 666	cmp.w	#0x7fff,%d2
 667	jeq	fp_nd_huge		| NaN / infinitive.
 668	sub.w	#0x4000-0x3ff,%d2	| will the exponent fit?
 669	jcs	fp_nd_small		| too small.
 670	cmp.w	#0x7fe,%d2
 671	jcc	fp_nd_large		| too big.
 672	addq.l	#4,%a0
 673	move.l	(%a0),%d0		| low lword of mantissa
 674	| now, round off the low 11 bits.
 675fp_nd_round:
 676	moveq	#21,%d1
 677	lsl.l	%d1,%d0			| keep 11 low bits.
 678	jne	fp_nd_checkround	| Are they non-zero?
 679	| nothing to do here
 6809:	subq.l	#8,%a0
 681	printf	PNORM,"%p(",1,%a0
 682	printx	PNORM,%a0@
 683	printf	PNORM,")\n"
 684	rts
 685	| Be careful with the X bit! It contains the lsb
 686	| from the shift above, it is needed for round to nearest.
 687fp_nd_checkround:
 688	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
 689	and.w	#0xf800,(2,%a0)		| clear bits 0-10
 690	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
 691	jne	2f			| %d2 == 0, round to nearest
 692	tst.l	%d0			| test guard bit
 693	jpl	9b			| zero is closer
 694	| here we test the X bit by adding it to %d2
 695	clr.w	%d2			| first set z bit, addx only clears it
 696	addx.w	%d2,%d2			| test lsb bit
 697	| IEEE754-specified "round to even" behaviour.  If the guard
 698	| bit is set, then the number is odd, so rounding works like
 699	| in grade-school arithmetic (i.e. 1.5 rounds to 2.0)
 700	| Otherwise, an equal distance rounds towards zero, so as not
 701	| to produce an odd number.  This is strange, but it is what
 702	| the standard says.
 703	jne	fp_nd_doroundup		| round to infinity
 704	lsl.l	#1,%d0			| check low bits
 705	jeq	9b			| round to zero
 706fp_nd_doroundup:
 707	| round (the mantissa, that is) towards infinity
 708	add.l	#0x800,(%a0)
 709	jcc	9b			| no overflow, good.
 710	addq.l	#1,-(%a0)		| extend to high lword
 711	jcc	1f			| no overflow, good.
 712	| Yow! we have managed to overflow the mantissa.  Since this
 713	| only happens when %d1 was 0xfffff800, it is now zero, so
 714	| reset the high bit, and increment the exponent.
 715	move.w	#0x8000,(%a0)
 716	addq.w	#1,-(%a0)
 717	cmp.w	#0x43ff,(%a0)+		| exponent now overflown?
 718	jeq	fp_nd_large		| yes, so make it infinity.
 7191:	subq.l	#4,%a0
 720	printf	PNORM,"%p(",1,%a0
 721	printx	PNORM,%a0@
 722	printf	PNORM,")\n"
 723	rts
 7242:	subq.w	#2,%d2
 725	jcs	9b			| %d2 < 2, round to zero
 726	jhi	3f			| %d2 > 2, round to +infinity
 727	| Round to +Inf or -Inf.  High word of %d2 contains the
 728	| sign of the number, by the way.
 729	swap	%d2			| to -inf
 730	tst.b	%d2
 731	jne	fp_nd_doroundup		| negative, round to infinity
 732	jra	9b			| positive, round to zero
 7333:	swap	%d2			| to +inf
 734	tst.b	%d2
 735	jeq	fp_nd_doroundup		| positive, round to infinity
 736	jra	9b			| negative, round to zero
 737	| Exponent underflow.  Try to make a denormal, and set it to
 738	| the smallest possible fraction if this fails.
 739fp_nd_small:
 740	fp_set_sr FPSR_EXC_UNFL		| set UNFL bit
 741	move.w	#0x3c01,(-2,%a0)	| 2**-1022
 742	neg.w	%d2			| degree of underflow
 743	cmp.w	#32,%d2			| single or double shift?
 744	jcc	1f
 745	| Again, another 64-bit double shift.
 746	move.l	(%a0),%d0
 747	move.l	%d0,%d1
 748	lsr.l	%d2,%d0
 749	move.l	%d0,(%a0)+
 750	move.l	(%a0),%d0
 751	lsr.l	%d2,%d0
 752	neg.w	%d2
 753	add.w	#32,%d2
 754	lsl.l	%d2,%d1
 755	or.l	%d1,%d0
 756	move.l	(%a0),%d1
 757	move.l	%d0,(%a0)
 758	| Check to see if we shifted off any significant bits
 759	lsl.l	%d2,%d1
 760	jeq	fp_nd_round		| Nope, round.
 761	bset	#0,%d0			| Yes, so set the "sticky bit".
 762	jra	fp_nd_round		| Now, round.
 763	| Another 64-bit single shift and store
 7641:	sub.w	#32,%d2
 765	cmp.w	#32,%d2			| Do we really need to shift?
 766	jcc	2f			| No, the number is too small.
 767	move.l	(%a0),%d0
 768	clr.l	(%a0)+
 769	move.l	%d0,%d1
 770	lsr.l	%d2,%d0
 771	neg.w	%d2
 772	add.w	#32,%d2
 773	| Again, check to see if we shifted off any significant bits.
 774	tst.l	(%a0)
 775	jeq	1f
 776	bset	#0,%d0			| Sticky bit.
 7771:	move.l	%d0,(%a0)
 778	lsl.l	%d2,%d1
 779	jeq	fp_nd_round
 780	bset	#0,%d0
 781	jra	fp_nd_round
 782	| Sorry, the number is just too small.
 7832:	clr.l	(%a0)+
 784	clr.l	(%a0)
 785	moveq	#1,%d0			| Smallest possible fraction,
 786	jra	fp_nd_round		| round as desired.
 787	| zero and denormalized
 788fp_nd_zero:
 789	tst.l	(%a0)+
 790	jne	1f
 791	tst.l	(%a0)
 792	jne	1f
 793	subq.l	#8,%a0
 794	printf	PNORM,"%p(",1,%a0
 795	printx	PNORM,%a0@
 796	printf	PNORM,")\n"
 797	rts				| zero.  nothing to do.
 798	| These are not merely subnormal numbers, but true denormals,
 799	| i.e. pathologically small (exponent is 2**-16383) numbers.
 800	| It is clearly impossible for even a normal extended number
 801	| with that exponent to fit into double precision, so just
 802	| write these ones off as "too darn small".
 8031:	fp_set_sr FPSR_EXC_UNFL		| Set UNFL bit
 804	clr.l	(%a0)
 805	clr.l	-(%a0)
 806	move.w	#0x3c01,-(%a0)		| i.e. 2**-1022
 807	addq.l	#6,%a0
 808	moveq	#1,%d0
 809	jra	fp_nd_round		| round.
 810	| Exponent overflow.  Just call it infinity.
 811fp_nd_large:
 812	move.w	#0x7ff,%d0
 813	and.w	(6,%a0),%d0
 814	jeq	1f
 815	fp_set_sr FPSR_EXC_INEX2
 8161:	fp_set_sr FPSR_EXC_OVFL
 817	move.w	(FPD_RND,FPDATA),%d2
 818	jne	3f			| %d2 = 0 round to nearest
 8191:	move.w	#0x7fff,(-2,%a0)
 820	clr.l	(%a0)+
 821	clr.l	(%a0)
 8222:	subq.l	#8,%a0
 823	printf	PNORM,"%p(",1,%a0
 824	printx	PNORM,%a0@
 825	printf	PNORM,")\n"
 826	rts
 8273:	subq.w	#2,%d2
 828	jcs	5f			| %d2 < 2, round to zero
 829	jhi	4f			| %d2 > 2, round to +infinity
 830	tst.b	(-3,%a0)		| to -inf
 831	jne	1b
 832	jra	5f
 8334:	tst.b	(-3,%a0)		| to +inf
 834	jeq	1b
 8355:	move.w	#0x43fe,(-2,%a0)
 836	moveq	#-1,%d0
 837	move.l	%d0,(%a0)+
 838	move.w	#0xf800,%d0
 839	move.l	%d0,(%a0)
 840	jra	2b
 841	| Infinities or NaNs
 842fp_nd_huge:
 843	subq.l	#4,%a0
 844	printf	PNORM,"%p(",1,%a0
 845	printx	PNORM,%a0@
 846	printf	PNORM,")\n"
 847	rts
 848
 849	| fp_normalize_single:
 850	| normalize an extended with single (23-bit) precision
 851	| args:	 %a0 (struct fp_ext *)
 852
 853fp_normalize_single:
 854	printf	PNORM,"ns: %p(",1,%a0
 855	printx	PNORM,%a0@
 856	printf	PNORM,") "
 857	addq.l	#2,%a0
 858	move.w	(%a0)+,%d2
 859	jeq	fp_ns_zero		| zero / denormalized
 860	cmp.w	#0x7fff,%d2
 861	jeq	fp_ns_huge		| NaN / infinitive.
 862	sub.w	#0x4000-0x7f,%d2	| will the exponent fit?
 863	jcs	fp_ns_small		| too small.
 864	cmp.w	#0xfe,%d2
 865	jcc	fp_ns_large		| too big.
 866	move.l	(%a0)+,%d0		| get high lword of mantissa
 867fp_ns_round:
 868	tst.l	(%a0)			| check the low lword
 869	jeq	1f
 870	| Set a sticky bit if it is non-zero.  This should only
 871	| affect the rounding in what would otherwise be equal-
 872	| distance situations, which is what we want it to do.
 873	bset	#0,%d0
 8741:	clr.l	(%a0)			| zap it from memory.
 875	| now, round off the low 8 bits of the hi lword.
 876	tst.b	%d0			| 8 low bits.
 877	jne	fp_ns_checkround	| Are they non-zero?
 878	| nothing to do here
 879	subq.l	#8,%a0
 880	printf	PNORM,"%p(",1,%a0
 881	printx	PNORM,%a0@
 882	printf	PNORM,")\n"
 883	rts
 884fp_ns_checkround:
 885	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
 886	clr.b	-(%a0)			| clear low byte of high lword
 887	subq.l	#3,%a0
 888	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
 889	jne	2f			| %d2 == 0, round to nearest
 890	tst.b	%d0			| test guard bit
 891	jpl	9f			| zero is closer
 892	btst	#8,%d0			| test lsb bit
 893	| round to even behaviour, see above.
 894	jne	fp_ns_doroundup		| round to infinity
 895	lsl.b	#1,%d0			| check low bits
 896	jeq	9f			| round to zero
 897fp_ns_doroundup:
 898	| round (the mantissa, that is) towards infinity
 899	add.l	#0x100,(%a0)
 900	jcc	9f			| no overflow, good.
 901	| Overflow.  This means that the %d1 was 0xffffff00, so it
 902	| is now zero.  We will set the mantissa to reflect this, and
 903	| increment the exponent (checking for overflow there too)
 904	move.w	#0x8000,(%a0)
 905	addq.w	#1,-(%a0)
 906	cmp.w	#0x407f,(%a0)+		| exponent now overflown?
 907	jeq	fp_ns_large		| yes, so make it infinity.
 9089:	subq.l	#4,%a0
 909	printf	PNORM,"%p(",1,%a0
 910	printx	PNORM,%a0@
 911	printf	PNORM,")\n"
 912	rts
 913	| check nondefault rounding modes
 9142:	subq.w	#2,%d2
 915	jcs	9b			| %d2 < 2, round to zero
 916	jhi	3f			| %d2 > 2, round to +infinity
 917	tst.b	(-3,%a0)		| to -inf
 918	jne	fp_ns_doroundup		| negative, round to infinity
 919	jra	9b			| positive, round to zero
 9203:	tst.b	(-3,%a0)		| to +inf
 921	jeq	fp_ns_doroundup		| positive, round to infinity
 922	jra	9b			| negative, round to zero
 923	| Exponent underflow.  Try to make a denormal, and set it to
 924	| the smallest possible fraction if this fails.
 925fp_ns_small:
 926	fp_set_sr FPSR_EXC_UNFL		| set UNFL bit
 927	move.w	#0x3f81,(-2,%a0)	| 2**-126
 928	neg.w	%d2			| degree of underflow
 929	cmp.w	#32,%d2			| single or double shift?
 930	jcc	2f
 931	| a 32-bit shift.
 932	move.l	(%a0),%d0
 933	move.l	%d0,%d1
 934	lsr.l	%d2,%d0
 935	move.l	%d0,(%a0)+
 936	| Check to see if we shifted off any significant bits.
 937	neg.w	%d2
 938	add.w	#32,%d2
 939	lsl.l	%d2,%d1
 940	jeq	1f
 941	bset	#0,%d0			| Sticky bit.
 942	| Check the lower lword
 9431:	tst.l	(%a0)
 944	jeq	fp_ns_round
 945	clr	(%a0)
 946	bset	#0,%d0			| Sticky bit.
 947	jra	fp_ns_round
 948	| Sorry, the number is just too small.
 9492:	clr.l	(%a0)+
 950	clr.l	(%a0)
 951	moveq	#1,%d0			| Smallest possible fraction,
 952	jra	fp_ns_round		| round as desired.
 953	| Exponent overflow.  Just call it infinity.
 954fp_ns_large:
 955	tst.b	(3,%a0)
 956	jeq	1f
 957	fp_set_sr FPSR_EXC_INEX2
 9581:	fp_set_sr FPSR_EXC_OVFL
 959	move.w	(FPD_RND,FPDATA),%d2
 960	jne	3f			| %d2 = 0 round to nearest
 9611:	move.w	#0x7fff,(-2,%a0)
 962	clr.l	(%a0)+
 963	clr.l	(%a0)
 9642:	subq.l	#8,%a0
 965	printf	PNORM,"%p(",1,%a0
 966	printx	PNORM,%a0@
 967	printf	PNORM,")\n"
 968	rts
 9693:	subq.w	#2,%d2
 970	jcs	5f			| %d2 < 2, round to zero
 971	jhi	4f			| %d2 > 2, round to +infinity
 972	tst.b	(-3,%a0)		| to -inf
 973	jne	1b
 974	jra	5f
 9754:	tst.b	(-3,%a0)		| to +inf
 976	jeq	1b
 9775:	move.w	#0x407e,(-2,%a0)
 978	move.l	#0xffffff00,(%a0)+
 979	clr.l	(%a0)
 980	jra	2b
 981	| zero and denormalized
 982fp_ns_zero:
 983	tst.l	(%a0)+
 984	jne	1f
 985	tst.l	(%a0)
 986	jne	1f
 987	subq.l	#8,%a0
 988	printf	PNORM,"%p(",1,%a0
 989	printx	PNORM,%a0@
 990	printf	PNORM,")\n"
 991	rts				| zero.  nothing to do.
 992	| These are not merely subnormal numbers, but true denormals,
 993	| i.e. pathologically small (exponent is 2**-16383) numbers.
 994	| It is clearly impossible for even a normal extended number
 995	| with that exponent to fit into single precision, so just
 996	| write these ones off as "too darn small".
 9971:	fp_set_sr FPSR_EXC_UNFL		| Set UNFL bit
 998	clr.l	(%a0)
 999	clr.l	-(%a0)
1000	move.w	#0x3f81,-(%a0)		| i.e. 2**-126
1001	addq.l	#6,%a0
1002	moveq	#1,%d0
1003	jra	fp_ns_round		| round.
1004	| Infinities or NaNs
1005fp_ns_huge:
1006	subq.l	#4,%a0
1007	printf	PNORM,"%p(",1,%a0
1008	printx	PNORM,%a0@
1009	printf	PNORM,")\n"
1010	rts
1011
1012	| fp_normalize_single_fast:
1013	| normalize an extended with single (23-bit) precision
1014	| this is only used by fsgldiv/fsgdlmul, where the
1015	| operand is not completly normalized.
1016	| args:	 %a0 (struct fp_ext *)
1017
1018fp_normalize_single_fast:
1019	printf	PNORM,"nsf: %p(",1,%a0
1020	printx	PNORM,%a0@
1021	printf	PNORM,") "
1022	addq.l	#2,%a0
1023	move.w	(%a0)+,%d2
1024	cmp.w	#0x7fff,%d2
1025	jeq	fp_nsf_huge		| NaN / infinitive.
1026	move.l	(%a0)+,%d0		| get high lword of mantissa
1027fp_nsf_round:
1028	tst.l	(%a0)			| check the low lword
1029	jeq	1f
1030	| Set a sticky bit if it is non-zero.  This should only
1031	| affect the rounding in what would otherwise be equal-
1032	| distance situations, which is what we want it to do.
1033	bset	#0,%d0
10341:	clr.l	(%a0)			| zap it from memory.
1035	| now, round off the low 8 bits of the hi lword.
1036	tst.b	%d0			| 8 low bits.
1037	jne	fp_nsf_checkround	| Are they non-zero?
1038	| nothing to do here
1039	subq.l	#8,%a0
1040	printf	PNORM,"%p(",1,%a0
1041	printx	PNORM,%a0@
1042	printf	PNORM,")\n"
1043	rts
1044fp_nsf_checkround:
1045	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
1046	clr.b	-(%a0)			| clear low byte of high lword
1047	subq.l	#3,%a0
1048	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1049	jne	2f			| %d2 == 0, round to nearest
1050	tst.b	%d0			| test guard bit
1051	jpl	9f			| zero is closer
1052	btst	#8,%d0			| test lsb bit
1053	| round to even behaviour, see above.
1054	jne	fp_nsf_doroundup		| round to infinity
1055	lsl.b	#1,%d0			| check low bits
1056	jeq	9f			| round to zero
1057fp_nsf_doroundup:
1058	| round (the mantissa, that is) towards infinity
1059	add.l	#0x100,(%a0)
1060	jcc	9f			| no overflow, good.
1061	| Overflow.  This means that the %d1 was 0xffffff00, so it
1062	| is now zero.  We will set the mantissa to reflect this, and
1063	| increment the exponent (checking for overflow there too)
1064	move.w	#0x8000,(%a0)
1065	addq.w	#1,-(%a0)
1066	cmp.w	#0x407f,(%a0)+		| exponent now overflown?
1067	jeq	fp_nsf_large		| yes, so make it infinity.
10689:	subq.l	#4,%a0
1069	printf	PNORM,"%p(",1,%a0
1070	printx	PNORM,%a0@
1071	printf	PNORM,")\n"
1072	rts
1073	| check nondefault rounding modes
10742:	subq.w	#2,%d2
1075	jcs	9b			| %d2 < 2, round to zero
1076	jhi	3f			| %d2 > 2, round to +infinity
1077	tst.b	(-3,%a0)		| to -inf
1078	jne	fp_nsf_doroundup	| negative, round to infinity
1079	jra	9b			| positive, round to zero
10803:	tst.b	(-3,%a0)		| to +inf
1081	jeq	fp_nsf_doroundup		| positive, round to infinity
1082	jra	9b			| negative, round to zero
1083	| Exponent overflow.  Just call it infinity.
1084fp_nsf_large:
1085	tst.b	(3,%a0)
1086	jeq	1f
1087	fp_set_sr FPSR_EXC_INEX2
10881:	fp_set_sr FPSR_EXC_OVFL
1089	move.w	(FPD_RND,FPDATA),%d2
1090	jne	3f			| %d2 = 0 round to nearest
10911:	move.w	#0x7fff,(-2,%a0)
1092	clr.l	(%a0)+
1093	clr.l	(%a0)
10942:	subq.l	#8,%a0
1095	printf	PNORM,"%p(",1,%a0
1096	printx	PNORM,%a0@
1097	printf	PNORM,")\n"
1098	rts
10993:	subq.w	#2,%d2
1100	jcs	5f			| %d2 < 2, round to zero
1101	jhi	4f			| %d2 > 2, round to +infinity
1102	tst.b	(-3,%a0)		| to -inf
1103	jne	1b
1104	jra	5f
11054:	tst.b	(-3,%a0)		| to +inf
1106	jeq	1b
11075:	move.w	#0x407e,(-2,%a0)
1108	move.l	#0xffffff00,(%a0)+
1109	clr.l	(%a0)
1110	jra	2b
1111	| Infinities or NaNs
1112fp_nsf_huge:
1113	subq.l	#4,%a0
1114	printf	PNORM,"%p(",1,%a0
1115	printx	PNORM,%a0@
1116	printf	PNORM,")\n"
1117	rts
1118
1119	| conv_ext2int (macro):
1120	| Generates a subroutine that converts an extended value to an
1121	| integer of a given size, again, with the appropriate type of
1122	| rounding.
1123
1124	| Macro arguments:
1125	| s:	size, as given in an assembly instruction.
1126	| b:	number of bits in that size.
1127
1128	| Subroutine arguments:
1129	| %a0:	source (struct fp_ext *)
1130
1131	| Returns the integer in %d0 (like it should)
1132
1133.macro conv_ext2int s,b
1134	.set	inf,(1<<(\b-1))-1	| i.e. MAXINT
1135	printf	PCONV,"e2i%d: %p(",2,#\b,%a0
1136	printx	PCONV,%a0@
1137	printf	PCONV,") "
1138	addq.l	#2,%a0
1139	move.w	(%a0)+,%d2		| exponent
1140	jeq	fp_e2i_zero\b		| zero / denorm (== 0, here)
1141	cmp.w	#0x7fff,%d2
1142	jeq	fp_e2i_huge\b		| Inf / NaN
1143	sub.w	#0x3ffe,%d2
1144	jcs	fp_e2i_small\b
1145	cmp.w	#\b,%d2
1146	jhi	fp_e2i_large\b
1147	move.l	(%a0),%d0
1148	move.l	%d0,%d1
1149	lsl.l	%d2,%d1
1150	jne	fp_e2i_round\b
1151	tst.l	(4,%a0)
1152	jne	fp_e2i_round\b
1153	neg.w	%d2
1154	add.w	#32,%d2
1155	lsr.l	%d2,%d0
11569:	tst.w	(-4,%a0)
1157	jne	1f
1158	tst.\s	%d0
1159	jmi	fp_e2i_large\b
1160	printf	PCONV,"-> %p\n",1,%d0
1161	rts
11621:	neg.\s	%d0
1163	jeq	1f
1164	jpl	fp_e2i_large\b
11651:	printf	PCONV,"-> %p\n",1,%d0
1166	rts
1167fp_e2i_round\b:
1168	fp_set_sr FPSR_EXC_INEX2	| INEX2 bit
1169	neg.w	%d2
1170	add.w	#32,%d2
1171	.if	\b>16
1172	jeq	5f
1173	.endif
1174	lsr.l	%d2,%d0
1175	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1176	jne	2f			| %d2 == 0, round to nearest
1177	tst.l	%d1			| test guard bit
1178	jpl	9b			| zero is closer
1179	btst	%d2,%d0			| test lsb bit (%d2 still 0)
1180	jne	fp_e2i_doroundup\b
1181	lsl.l	#1,%d1			| check low bits
1182	jne	fp_e2i_doroundup\b
1183	tst.l	(4,%a0)
1184	jeq	9b
1185fp_e2i_doroundup\b:
1186	addq.l	#1,%d0
1187	jra	9b
1188	| check nondefault rounding modes
11892:	subq.w	#2,%d2
1190	jcs	9b			| %d2 < 2, round to zero
1191	jhi	3f			| %d2 > 2, round to +infinity
1192	tst.w	(-4,%a0)		| to -inf
1193	jne	fp_e2i_doroundup\b	| negative, round to infinity
1194	jra	9b			| positive, round to zero
11953:	tst.w	(-4,%a0)		| to +inf
1196	jeq	fp_e2i_doroundup\b	| positive, round to infinity
1197	jra	9b	| negative, round to zero
1198	| we are only want -2**127 get correctly rounded here,
1199	| since the guard bit is in the lower lword.
1200	| everything else ends up anyway as overflow.
1201	.if	\b>16
12025:	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1203	jne	2b			| %d2 == 0, round to nearest
1204	move.l	(4,%a0),%d1		| test guard bit
1205	jpl	9b			| zero is closer
1206	lsl.l	#1,%d1			| check low bits
1207	jne	fp_e2i_doroundup\b
1208	jra	9b
1209	.endif
1210fp_e2i_zero\b:
1211	clr.l	%d0
1212	tst.l	(%a0)+
1213	jne	1f
1214	tst.l	(%a0)
1215	jeq	3f
12161:	subq.l	#4,%a0
1217	fp_clr_sr FPSR_EXC_UNFL		| fp_normalize_ext has set this bit
1218fp_e2i_small\b:
1219	fp_set_sr FPSR_EXC_INEX2
1220	clr.l	%d0
1221	move.w	(FPD_RND,FPDATA),%d2	| rounding mode
1222	subq.w	#2,%d2
1223	jcs	3f			| %d2 < 2, round to nearest/zero
1224	jhi	2f			| %d2 > 2, round to +infinity
1225	tst.w	(-4,%a0)		| to -inf
1226	jeq	3f
1227	subq.\s	#1,%d0
1228	jra	3f
12292:	tst.w	(-4,%a0)		| to +inf
1230	jne	3f
1231	addq.\s	#1,%d0
12323:	printf	PCONV,"-> %p\n",1,%d0
1233	rts
1234fp_e2i_large\b:
1235	fp_set_sr FPSR_EXC_OPERR
1236	move.\s	#inf,%d0
1237	tst.w	(-4,%a0)
1238	jeq	1f
1239	addq.\s	#1,%d0
12401:	printf	PCONV,"-> %p\n",1,%d0
1241	rts
1242fp_e2i_huge\b:
1243	move.\s	(%a0),%d0
1244	tst.l	(%a0)
1245	jne	1f
1246	tst.l	(%a0)
1247	jeq	fp_e2i_large\b
1248	| fp_normalize_ext has set this bit already
1249	| and made the number nonsignaling
12501:	fp_tst_sr FPSR_EXC_SNAN
1251	jne	1f
1252	fp_set_sr FPSR_EXC_OPERR
12531:	printf	PCONV,"-> %p\n",1,%d0
1254	rts
1255.endm
1256
1257fp_conv_ext2long:
1258	conv_ext2int l,32
1259
1260fp_conv_ext2short:
1261	conv_ext2int w,16
1262
1263fp_conv_ext2byte:
1264	conv_ext2int b,8
1265
1266fp_conv_ext2double:
1267	jsr	fp_normalize_double
1268	printf	PCONV,"e2d: %p(",1,%a0
1269	printx	PCONV,%a0@
1270	printf	PCONV,"), "
1271	move.l	(%a0)+,%d2
1272	cmp.w	#0x7fff,%d2
1273	jne	1f
1274	move.w	#0x7ff,%d2
1275	move.l	(%a0)+,%d0
1276	jra	2f
12771:	sub.w	#0x3fff-0x3ff,%d2
1278	move.l	(%a0)+,%d0
1279	jmi	2f
1280	clr.w	%d2
12812:	lsl.w	#5,%d2
1282	lsl.l	#7,%d2
1283	lsl.l	#8,%d2
1284	move.l	%d0,%d1
1285	lsl.l	#1,%d0
1286	lsr.l	#4,%d0
1287	lsr.l	#8,%d0
1288	or.l	%d2,%d0
1289	putuser.l %d0,(%a1)+,fp_err_ua2,%a1
1290	moveq	#21,%d0
1291	lsl.l	%d0,%d1
1292	move.l	(%a0),%d0
1293	lsr.l	#4,%d0
1294	lsr.l	#7,%d0
1295	or.l	%d1,%d0
1296	putuser.l %d0,(%a1),fp_err_ua2,%a1
1297#ifdef FPU_EMU_DEBUG
1298	getuser.l %a1@(-4),%d0,fp_err_ua2,%a1
1299	getuser.l %a1@(0),%d1,fp_err_ua2,%a1
1300	printf	PCONV,"%p(%08x%08x)\n",3,%a1,%d0,%d1
1301#endif
1302	rts
1303
1304fp_conv_ext2single:
1305	jsr	fp_normalize_single
1306	printf	PCONV,"e2s: %p(",1,%a0
1307	printx	PCONV,%a0@
1308	printf	PCONV,"), "
1309	move.l	(%a0)+,%d1
1310	cmp.w	#0x7fff,%d1
1311	jne	1f
1312	move.w	#0xff,%d1
1313	move.l	(%a0)+,%d0
1314	jra	2f
13151:	sub.w	#0x3fff-0x7f,%d1
1316	move.l	(%a0)+,%d0
1317	jmi	2f
1318	clr.w	%d1
13192:	lsl.w	#8,%d1
1320	lsl.l	#7,%d1
1321	lsl.l	#8,%d1
1322	bclr	#31,%d0
1323	lsr.l	#8,%d0
1324	or.l	%d1,%d0
1325	printf	PCONV,"%08x\n",1,%d0
1326	rts
1327
1328	| special return addresses for instr that
1329	| encode the rounding precision in the opcode
1330	| (e.g. fsmove,fdmove)
1331
1332fp_finalrounding_single:
1333	addq.l	#8,%sp
1334	jsr	fp_normalize_ext
1335	jsr	fp_normalize_single
1336	jra	fp_finaltest
1337
1338fp_finalrounding_single_fast:
1339	addq.l	#8,%sp
1340	jsr	fp_normalize_ext
1341	jsr	fp_normalize_single_fast
1342	jra	fp_finaltest
1343
1344fp_finalrounding_double:
1345	addq.l	#8,%sp
1346	jsr	fp_normalize_ext
1347	jsr	fp_normalize_double
1348	jra	fp_finaltest
1349
1350	| fp_finaltest:
1351	| set the emulated status register based on the outcome of an
1352	| emulated instruction.
1353
1354fp_finalrounding:
1355	addq.l	#8,%sp
1356|	printf	,"f: %p\n",1,%a0
1357	jsr	fp_normalize_ext
1358	move.w	(FPD_PREC,FPDATA),%d0
1359	subq.w	#1,%d0
1360	jcs	fp_finaltest
1361	jne	1f
1362	jsr	fp_normalize_single
1363	jra	2f
13641:	jsr	fp_normalize_double
13652:|	printf	,"f: %p\n",1,%a0
1366fp_finaltest:
1367	| First, we do some of the obvious tests for the exception
1368	| status byte and condition code bytes of fp_sr here, so that
1369	| they do not have to be handled individually by every
1370	| emulated instruction.
1371	clr.l	%d0
1372	addq.l	#1,%a0
1373	tst.b	(%a0)+			| sign
1374	jeq	1f
1375	bset	#FPSR_CC_NEG-24,%d0	| N bit
13761:	cmp.w	#0x7fff,(%a0)+		| exponent
1377	jeq	2f
1378	| test for zero
1379	moveq	#FPSR_CC_Z-24,%d1
1380	tst.l	(%a0)+
1381	jne	9f
1382	tst.l	(%a0)
1383	jne	9f
1384	jra	8f
1385	| infinitiv and NAN
13862:	moveq	#FPSR_CC_NAN-24,%d1
1387	move.l	(%a0)+,%d2
1388	lsl.l	#1,%d2			| ignore high bit
1389	jne	8f
1390	tst.l	(%a0)
1391	jne	8f
1392	moveq	#FPSR_CC_INF-24,%d1
13938:	bset	%d1,%d0
13949:	move.b	%d0,(FPD_FPSR+0,FPDATA)	| set condition test result
1395	| move instructions enter here
1396	| Here, we test things in the exception status byte, and set
1397	| other things in the accrued exception byte accordingly.
1398	| Emulated instructions can set various things in the former,
1399	| as defined in fp_emu.h.
1400fp_final:
1401	move.l	(FPD_FPSR,FPDATA),%d0
1402#if 0
1403	btst	#FPSR_EXC_SNAN,%d0	| EXC_SNAN
1404	jne	1f
1405	btst	#FPSR_EXC_OPERR,%d0	| EXC_OPERR
1406	jeq	2f
14071:	bset	#FPSR_AEXC_IOP,%d0	| set IOP bit
14082:	btst	#FPSR_EXC_OVFL,%d0	| EXC_OVFL
1409	jeq	1f
1410	bset	#FPSR_AEXC_OVFL,%d0	| set OVFL bit
14111:	btst	#FPSR_EXC_UNFL,%d0	| EXC_UNFL
1412	jeq	1f
1413	btst	#FPSR_EXC_INEX2,%d0	| EXC_INEX2
1414	jeq	1f
1415	bset	#FPSR_AEXC_UNFL,%d0	| set UNFL bit
14161:	btst	#FPSR_EXC_DZ,%d0	| EXC_INEX1
1417	jeq	1f
1418	bset	#FPSR_AEXC_DZ,%d0	| set DZ bit
14191:	btst	#FPSR_EXC_OVFL,%d0	| EXC_OVFL
1420	jne	1f
1421	btst	#FPSR_EXC_INEX2,%d0	| EXC_INEX2
1422	jne	1f
1423	btst	#FPSR_EXC_INEX1,%d0	| EXC_INEX1
1424	jeq	2f
14251:	bset	#FPSR_AEXC_INEX,%d0	| set INEX bit
14262:	move.l	%d0,(FPD_FPSR,FPDATA)
1427#else
1428	| same as above, greatly optimized, but untested (yet)
1429	move.l	%d0,%d2
1430	lsr.l	#5,%d0
1431	move.l	%d0,%d1
1432	lsr.l	#4,%d1
1433	or.l	%d0,%d1
1434	and.b	#0x08,%d1
1435	move.l	%d2,%d0
1436	lsr.l	#6,%d0
1437	or.l	%d1,%d0
1438	move.l	%d2,%d1
1439	lsr.l	#4,%d1
1440	or.b	#0xdf,%d1
1441	and.b	%d1,%d0
1442	move.l	%d2,%d1
1443	lsr.l	#7,%d1
1444	and.b	#0x80,%d1
1445	or.b	%d1,%d0
1446	and.b	#0xf8,%d0
1447	or.b	%d0,%d2
1448	move.l	%d2,(FPD_FPSR,FPDATA)
1449#endif
1450	move.b	(FPD_FPSR+2,FPDATA),%d0
1451	and.b	(FPD_FPCR+2,FPDATA),%d0
1452	jeq	1f
1453	printf	,"send signal!!!\n"
14541:	jra	fp_end