Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*---------------------------------------------------------------------------+
  3 |  fpu_etc.c                                                                |
  4 |                                                                           |
  5 | Implement a few FPU instructions.                                         |
  6 |                                                                           |
  7 | Copyright (C) 1992,1993,1994,1997                                         |
  8 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
  9 |                       Australia.  E-mail   billm@suburbia.net             |
 10 |                                                                           |
 11 |                                                                           |
 12 +---------------------------------------------------------------------------*/
 13
 14#include "fpu_system.h"
 15#include "exception.h"
 16#include "fpu_emu.h"
 17#include "status_w.h"
 18#include "reg_constant.h"
 19
 20static void fchs(FPU_REG *st0_ptr, u_char st0tag)
 21{
 22	if (st0tag ^ TAG_Empty) {
 23		signbyte(st0_ptr) ^= SIGN_NEG;
 24		clear_C1();
 25	} else
 26		FPU_stack_underflow();
 27}
 28
 29static void fabs(FPU_REG *st0_ptr, u_char st0tag)
 30{
 31	if (st0tag ^ TAG_Empty) {
 32		setpositive(st0_ptr);
 33		clear_C1();
 34	} else
 35		FPU_stack_underflow();
 36}
 37
 38static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
 39{
 40	switch (st0tag) {
 41	case TAG_Zero:
 42		setcc(SW_C3);
 43		break;
 44	case TAG_Valid:
 45		if (getsign(st0_ptr) == SIGN_POS)
 46			setcc(0);
 47		else
 48			setcc(SW_C0);
 49		break;
 50	case TAG_Special:
 51		switch (FPU_Special(st0_ptr)) {
 52		case TW_Denormal:
 53			if (getsign(st0_ptr) == SIGN_POS)
 54				setcc(0);
 55			else
 56				setcc(SW_C0);
 57			if (denormal_operand() < 0) {
 58#ifdef PECULIAR_486
 59				/* This is weird! */
 60				if (getsign(st0_ptr) == SIGN_POS)
 61					setcc(SW_C3);
 62#endif /* PECULIAR_486 */
 63				return;
 64			}
 65			break;
 66		case TW_NaN:
 67			setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
 68			EXCEPTION(EX_Invalid);
 69			break;
 70		case TW_Infinity:
 71			if (getsign(st0_ptr) == SIGN_POS)
 72				setcc(0);
 73			else
 74				setcc(SW_C0);
 75			break;
 76		default:
 77			setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
 78			EXCEPTION(EX_INTERNAL | 0x14);
 79			break;
 80		}
 81		break;
 82	case TAG_Empty:
 83		setcc(SW_C0 | SW_C2 | SW_C3);
 84		EXCEPTION(EX_StackUnder);
 85		break;
 86	}
 87}
 88
 89static void fxam(FPU_REG *st0_ptr, u_char st0tag)
 90{
 91	int c = 0;
 92	switch (st0tag) {
 93	case TAG_Empty:
 94		c = SW_C3 | SW_C0;
 95		break;
 96	case TAG_Zero:
 97		c = SW_C3;
 98		break;
 99	case TAG_Valid:
100		c = SW_C2;
101		break;
102	case TAG_Special:
103		switch (FPU_Special(st0_ptr)) {
104		case TW_Denormal:
105			c = SW_C2 | SW_C3;	/* Denormal */
106			break;
107		case TW_NaN:
108			/* We also use NaN for unsupported types. */
109			if ((st0_ptr->sigh & 0x80000000)
110			    && (exponent(st0_ptr) == EXP_OVER))
111				c = SW_C0;
112			break;
113		case TW_Infinity:
114			c = SW_C2 | SW_C0;
115			break;
116		}
117	}
118	if (getsign(st0_ptr) == SIGN_NEG)
119		c |= SW_C1;
120	setcc(c);
121}
122
123static FUNC_ST0 const fp_etc_table[] = {
124	fchs, fabs, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal,
125	ftst_, fxam, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal
126};
127
128void FPU_etc(void)
129{
130	(fp_etc_table[FPU_rm]) (&st(0), FPU_gettag0());
131}
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/*---------------------------------------------------------------------------+
  3 |  fpu_etc.c                                                                |
  4 |                                                                           |
  5 | Implement a few FPU instructions.                                         |
  6 |                                                                           |
  7 | Copyright (C) 1992,1993,1994,1997                                         |
  8 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
  9 |                       Australia.  E-mail   billm@suburbia.net             |
 10 |                                                                           |
 11 |                                                                           |
 12 +---------------------------------------------------------------------------*/
 13
 14#include "fpu_system.h"
 15#include "exception.h"
 16#include "fpu_emu.h"
 17#include "status_w.h"
 18#include "reg_constant.h"
 19
 20static void fchs(FPU_REG *st0_ptr, u_char st0tag)
 21{
 22	if (st0tag ^ TAG_Empty) {
 23		signbyte(st0_ptr) ^= SIGN_NEG;
 24		clear_C1();
 25	} else
 26		FPU_stack_underflow();
 27}
 28
 29static void fabs(FPU_REG *st0_ptr, u_char st0tag)
 30{
 31	if (st0tag ^ TAG_Empty) {
 32		setpositive(st0_ptr);
 33		clear_C1();
 34	} else
 35		FPU_stack_underflow();
 36}
 37
 38static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
 39{
 40	switch (st0tag) {
 41	case TAG_Zero:
 42		setcc(SW_C3);
 43		break;
 44	case TAG_Valid:
 45		if (getsign(st0_ptr) == SIGN_POS)
 46			setcc(0);
 47		else
 48			setcc(SW_C0);
 49		break;
 50	case TAG_Special:
 51		switch (FPU_Special(st0_ptr)) {
 52		case TW_Denormal:
 53			if (getsign(st0_ptr) == SIGN_POS)
 54				setcc(0);
 55			else
 56				setcc(SW_C0);
 57			if (denormal_operand() < 0) {
 58#ifdef PECULIAR_486
 59				/* This is weird! */
 60				if (getsign(st0_ptr) == SIGN_POS)
 61					setcc(SW_C3);
 62#endif /* PECULIAR_486 */
 63				return;
 64			}
 65			break;
 66		case TW_NaN:
 67			setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
 68			EXCEPTION(EX_Invalid);
 69			break;
 70		case TW_Infinity:
 71			if (getsign(st0_ptr) == SIGN_POS)
 72				setcc(0);
 73			else
 74				setcc(SW_C0);
 75			break;
 76		default:
 77			setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
 78			EXCEPTION(EX_INTERNAL | 0x14);
 79			break;
 80		}
 81		break;
 82	case TAG_Empty:
 83		setcc(SW_C0 | SW_C2 | SW_C3);
 84		EXCEPTION(EX_StackUnder);
 85		break;
 86	}
 87}
 88
 89static void fxam(FPU_REG *st0_ptr, u_char st0tag)
 90{
 91	int c = 0;
 92	switch (st0tag) {
 93	case TAG_Empty:
 94		c = SW_C3 | SW_C0;
 95		break;
 96	case TAG_Zero:
 97		c = SW_C3;
 98		break;
 99	case TAG_Valid:
100		c = SW_C2;
101		break;
102	case TAG_Special:
103		switch (FPU_Special(st0_ptr)) {
104		case TW_Denormal:
105			c = SW_C2 | SW_C3;	/* Denormal */
106			break;
107		case TW_NaN:
108			/* We also use NaN for unsupported types. */
109			if ((st0_ptr->sigh & 0x80000000)
110			    && (exponent(st0_ptr) == EXP_OVER))
111				c = SW_C0;
112			break;
113		case TW_Infinity:
114			c = SW_C2 | SW_C0;
115			break;
116		}
117	}
118	if (getsign(st0_ptr) == SIGN_NEG)
119		c |= SW_C1;
120	setcc(c);
121}
122
123static FUNC_ST0 const fp_etc_table[] = {
124	fchs, fabs, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal,
125	ftst_, fxam, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal
126};
127
128void FPU_etc(void)
129{
130	(fp_etc_table[FPU_rm]) (&st(0), FPU_gettag0());
131}