diff options
Diffstat (limited to 'sim/mips/interp.c')
-rw-r--r-- | sim/mips/interp.c | 1069 |
1 files changed, 0 insertions, 1069 deletions
diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 3e31ce4..5bd61a8 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -1892,1075 +1892,6 @@ undefined_result(sd,cia) } #endif /* WARN_RESULT */ -/*-- FPU support routines ---------------------------------------------------*/ - -/* Numbers are held in normalized form. The SINGLE and DOUBLE binary - formats conform to ANSI/IEEE Std 754-1985. */ -/* SINGLE precision floating: - * seeeeeeeefffffffffffffffffffffff - * s = 1bit = sign - * e = 8bits = exponent - * f = 23bits = fraction - */ -/* SINGLE precision fixed: - * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii - * s = 1bit = sign - * i = 31bits = integer - */ -/* DOUBLE precision floating: - * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff - * s = 1bit = sign - * e = 11bits = exponent - * f = 52bits = fraction - */ -/* DOUBLE precision fixed: - * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii - * s = 1bit = sign - * i = 63bits = integer - */ - -/* Extract sign-bit: */ -#define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0) -#define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0) -/* Extract biased exponent: */ -#define FP_S_be(v) (((v) >> 23) & 0xFF) -#define FP_D_be(v) (((v) >> 52) & 0x7FF) -/* Extract unbiased Exponent: */ -#define FP_S_e(v) (FP_S_be(v) - 0x7F) -#define FP_D_e(v) (FP_D_be(v) - 0x3FF) -/* Extract complete fraction field: */ -#define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23)) -#define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52)) -/* Extract numbered fraction bit: */ -#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0) -#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0) - -/* Explicit QNaN values used when value required: */ -#define FPQNaN_SINGLE (0x7FBFFFFF) -#define FPQNaN_WORD (0x7FFFFFFF) -#define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF) -#define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF) - -/* Explicit Infinity values used when required: */ -#define FPINF_SINGLE (0x7F800000) -#define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000) - -#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor"))) -#define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : (((v) == fmt_uninterpreted_32) ? "<uninterpreted_32>" : (((v) == fmt_uninterpreted_64) ? "<uninterpreted_64>" : "<format error>")))))))) - -uword64 -value_fpr (SIM_DESC sd, - sim_cpu *cpu, - address_word cia, - int fpr, - FP_formats fmt) -{ - uword64 value = 0; - int err = 0; - - /* Treat unused register values, as fixed-point 64bit values: */ - if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown)) -#if 1 - /* If request to read data as "uninterpreted", then use the current - encoding: */ - fmt = FPR_STATE[fpr]; -#else - fmt = fmt_long; -#endif - - /* For values not yet accessed, set to the desired format: */ - if (FPR_STATE[fpr] == fmt_uninterpreted) { - FPR_STATE[fpr] = fmt; -#ifdef DEBUG - printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt)); -#endif /* DEBUG */ - } - if (fmt != FPR_STATE[fpr]) { - sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia)); - FPR_STATE[fpr] = fmt_unknown; - } - - if (FPR_STATE[fpr] == fmt_unknown) { - /* Set QNaN value: */ - switch (fmt) { - case fmt_single: - value = FPQNaN_SINGLE; - break; - - case fmt_double: - value = FPQNaN_DOUBLE; - break; - - case fmt_word: - value = FPQNaN_WORD; - break; - - case fmt_long: - value = FPQNaN_LONG; - break; - - default: - err = -1; - break; - } - } else if (SizeFGR() == 64) { - switch (fmt) { - case fmt_single: - case fmt_word: - value = (FGR[fpr] & 0xFFFFFFFF); - break; - - case fmt_uninterpreted: - case fmt_double: - case fmt_long: - value = FGR[fpr]; - break; - - default : - err = -1; - break; - } - } else { - switch (fmt) { - case fmt_single: - case fmt_word: - value = (FGR[fpr] & 0xFFFFFFFF); - break; - - case fmt_uninterpreted: - case fmt_double: - case fmt_long: - if ((fpr & 1) == 0) { /* even registers only */ -#ifdef DEBUG - printf("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n", - fpr+1, pr_uword64( (uword64) FGR[fpr+1] ), - fpr, pr_uword64( (uword64) FGR[fpr] )); -#endif - value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF)); - } else { - SignalException(ReservedInstruction,0); - } - break; - - default : - err = -1; - break; - } - } - - if (err) - SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()"); - -#ifdef DEBUG - printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR()); -#endif /* DEBUG */ - - return(value); -} - -void -store_fpr (SIM_DESC sd, - sim_cpu *cpu, - address_word cia, - int fpr, - FP_formats fmt, - uword64 value) -{ - int err = 0; - -#ifdef DEBUG - printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d,\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR()); -#endif /* DEBUG */ - - if (SizeFGR() == 64) { - switch (fmt) { - case fmt_uninterpreted_32: - fmt = fmt_uninterpreted; - case fmt_single : - case fmt_word : - if (STATE_VERBOSE_P(SD)) - sim_io_eprintf (SD, "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n", - pr_addr(cia)); - FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF)); - FPR_STATE[fpr] = fmt; - break; - - case fmt_uninterpreted_64: - fmt = fmt_uninterpreted; - case fmt_uninterpreted: - case fmt_double : - case fmt_long : - FGR[fpr] = value; - FPR_STATE[fpr] = fmt; - break; - - default : - FPR_STATE[fpr] = fmt_unknown; - err = -1; - break; - } - } else { - switch (fmt) { - case fmt_uninterpreted_32: - fmt = fmt_uninterpreted; - case fmt_single : - case fmt_word : - FGR[fpr] = (value & 0xFFFFFFFF); - FPR_STATE[fpr] = fmt; - break; - - case fmt_uninterpreted_64: - fmt = fmt_uninterpreted; - case fmt_uninterpreted: - case fmt_double : - case fmt_long : - if ((fpr & 1) == 0) { /* even register number only */ - FGR[fpr+1] = (value >> 32); - FGR[fpr] = (value & 0xFFFFFFFF); - FPR_STATE[fpr + 1] = fmt; - FPR_STATE[fpr] = fmt; - } else { - FPR_STATE[fpr] = fmt_unknown; - FPR_STATE[fpr + 1] = fmt_unknown; - SignalException(ReservedInstruction,0); - } - break; - - default : - FPR_STATE[fpr] = fmt_unknown; - err = -1; - break; - } - } -#if defined(WARN_RESULT) - else - UndefinedResult(); -#endif /* WARN_RESULT */ - - if (err) - SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()"); - -#ifdef DEBUG - printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_uword64(FGR[fpr]),DOFMT(fmt)); -#endif /* DEBUG */ - - return; -} - -int -NaN(op,fmt) - uword64 op; - FP_formats fmt; -{ - int boolean = 0; - switch (fmt) { - case fmt_single: - case fmt_word: - { - sim_fpu wop; - sim_fpu_32to (&wop, op); - boolean = sim_fpu_is_nan (&wop); - break; - } - case fmt_double: - case fmt_long: - { - sim_fpu wop; - sim_fpu_64to (&wop, op); - boolean = sim_fpu_is_nan (&wop); - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG -printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt)); -#endif /* DEBUG */ - - return(boolean); -} - -int -Infinity(op,fmt) - uword64 op; - FP_formats fmt; -{ - int boolean = 0; - -#ifdef DEBUG - printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op)); -#endif /* DEBUG */ - - switch (fmt) { - case fmt_single: - { - sim_fpu wop; - sim_fpu_32to (&wop, op); - boolean = sim_fpu_is_infinity (&wop); - break; - } - case fmt_double: - { - sim_fpu wop; - sim_fpu_64to (&wop, op); - boolean = sim_fpu_is_infinity (&wop); - break; - } - default: - printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt)); - break; - } - -#ifdef DEBUG - printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt)); -#endif /* DEBUG */ - - return(boolean); -} - -int -Less(op1,op2,fmt) - uword64 op1; - uword64 op2; - FP_formats fmt; -{ - int boolean = 0; - - /* Argument checking already performed by the FPCOMPARE code */ - -#ifdef DEBUG - printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - boolean = sim_fpu_is_lt (&wop1, &wop2); - break; - } - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - boolean = sim_fpu_is_lt (&wop1, &wop2); - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt)); -#endif /* DEBUG */ - - return(boolean); -} - -int -Equal(op1,op2,fmt) - uword64 op1; - uword64 op2; - FP_formats fmt; -{ - int boolean = 0; - - /* Argument checking already performed by the FPCOMPARE code */ - -#ifdef DEBUG - printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - boolean = sim_fpu_is_eq (&wop1, &wop2); - break; - } - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - boolean = sim_fpu_is_eq (&wop1, &wop2); - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt)); -#endif /* DEBUG */ - - return(boolean); -} - -uword64 -AbsoluteValue(op,fmt) - uword64 op; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); -#endif /* DEBUG */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop; - unsigned32 ans; - sim_fpu_32to (&wop, op); - sim_fpu_abs (&wop, &wop); - sim_fpu_to32 (&ans, &wop); - result = ans; - break; - } - case fmt_double: - { - sim_fpu wop; - unsigned64 ans; - sim_fpu_64to (&wop, op); - sim_fpu_abs (&wop, &wop); - sim_fpu_to64 (&ans, &wop); - result = ans; - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - - return(result); -} - -uword64 -Negate(op,fmt) - uword64 op; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); -#endif /* DEBUG */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop; - unsigned32 ans; - sim_fpu_32to (&wop, op); - sim_fpu_neg (&wop, &wop); - sim_fpu_to32 (&ans, &wop); - result = ans; - break; - } - case fmt_double: - { - sim_fpu wop; - unsigned64 ans; - sim_fpu_64to (&wop, op); - sim_fpu_neg (&wop, &wop); - sim_fpu_to64 (&ans, &wop); - result = ans; - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - - return(result); -} - -uword64 -Add(op1,op2,fmt) - uword64 op1; - uword64 op2; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned32 res; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - sim_fpu_add (&ans, &wop1, &wop2); - sim_fpu_to32 (&res, &ans); - result = res; - break; - } - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned64 res; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - sim_fpu_add (&ans, &wop1, &wop2); - sim_fpu_to64 (&res, &ans); - result = res; - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} - -uword64 -Sub(op1,op2,fmt) - uword64 op1; - uword64 op2; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned32 res; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - sim_fpu_sub (&ans, &wop1, &wop2); - sim_fpu_to32 (&res, &ans); - result = res; - } - break; - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned64 res; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - sim_fpu_sub (&ans, &wop1, &wop2); - sim_fpu_to64 (&res, &ans); - result = res; - } - break; - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} - -uword64 -Multiply(op1,op2,fmt) - uword64 op1; - uword64 op2; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned32 res; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - sim_fpu_mul (&ans, &wop1, &wop2); - sim_fpu_to32 (&res, &ans); - result = res; - break; - } - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned64 res; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - sim_fpu_mul (&ans, &wop1, &wop2); - sim_fpu_to64 (&res, &ans); - result = res; - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} - -uword64 -Divide(op1,op2,fmt) - uword64 op1; - uword64 op2; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned32 res; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - sim_fpu_div (&ans, &wop1, &wop2); - sim_fpu_to32 (&res, &ans); - result = res; - break; - } - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu ans; - unsigned64 res; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - sim_fpu_div (&ans, &wop1, &wop2); - sim_fpu_to64 (&res, &ans); - result = res; - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} - -uword64 UNUSED -Recip(op,fmt) - uword64 op; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop; - sim_fpu ans; - unsigned32 res; - sim_fpu_32to (&wop, op); - sim_fpu_inv (&ans, &wop); - sim_fpu_to32 (&res, &ans); - result = res; - break; - } - case fmt_double: - { - sim_fpu wop; - sim_fpu ans; - unsigned64 res; - sim_fpu_64to (&wop, op); - sim_fpu_inv (&ans, &wop); - sim_fpu_to64 (&res, &ans); - result = res; - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} - -uword64 -SquareRoot(op,fmt) - uword64 op; - FP_formats fmt; -{ - uword64 result = 0; - -#ifdef DEBUG - printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) { - case fmt_single: - { - sim_fpu wop; - sim_fpu ans; - unsigned32 res; - sim_fpu_32to (&wop, op); - sim_fpu_sqrt (&ans, &wop); - sim_fpu_to32 (&res, &ans); - result = res; - break; - } - case fmt_double: - { - sim_fpu wop; - sim_fpu ans; - unsigned64 res; - sim_fpu_64to (&wop, op); - sim_fpu_sqrt (&ans, &wop); - sim_fpu_to64 (&res, &ans); - result = res; - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} - -#if 0 -uword64 -Max (uword64 op1, - uword64 op2, - FP_formats fmt) -{ - int cmp; - unsigned64 result; - -#ifdef DEBUG - printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) - { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - cmp = sim_fpu_cmp (&wop1, &wop2); - break; - } - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - cmp = sim_fpu_cmp (&wop1, &wop2); - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - - switch (cmp) - { - case SIM_FPU_IS_SNAN: - case SIM_FPU_IS_QNAN: - result = op1; - case SIM_FPU_IS_NINF: - case SIM_FPU_IS_NNUMBER: - case SIM_FPU_IS_NDENORM: - case SIM_FPU_IS_NZERO: - result = op2; /* op1 - op2 < 0 */ - case SIM_FPU_IS_PINF: - case SIM_FPU_IS_PNUMBER: - case SIM_FPU_IS_PDENORM: - case SIM_FPU_IS_PZERO: - result = op1; /* op1 - op2 > 0 */ - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} -#endif - -#if 0 -uword64 -Min (uword64 op1, - uword64 op2, - FP_formats fmt) -{ - int cmp; - unsigned64 result; - -#ifdef DEBUG - printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); -#endif /* DEBUG */ - - /* The registers must specify FPRs valid for operands of type - "fmt". If they are not valid, the result is undefined. */ - - /* The format type should already have been checked: */ - switch (fmt) - { - case fmt_single: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_32to (&wop1, op1); - sim_fpu_32to (&wop2, op2); - cmp = sim_fpu_cmp (&wop1, &wop2); - break; - } - case fmt_double: - { - sim_fpu wop1; - sim_fpu wop2; - sim_fpu_64to (&wop1, op1); - sim_fpu_64to (&wop2, op2); - cmp = sim_fpu_cmp (&wop1, &wop2); - break; - } - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - - switch (cmp) - { - case SIM_FPU_IS_SNAN: - case SIM_FPU_IS_QNAN: - result = op1; - case SIM_FPU_IS_NINF: - case SIM_FPU_IS_NNUMBER: - case SIM_FPU_IS_NDENORM: - case SIM_FPU_IS_NZERO: - result = op1; /* op1 - op2 < 0 */ - case SIM_FPU_IS_PINF: - case SIM_FPU_IS_PNUMBER: - case SIM_FPU_IS_PDENORM: - case SIM_FPU_IS_PZERO: - result = op2; /* op1 - op2 > 0 */ - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); -#endif /* DEBUG */ - - return(result); -} -#endif - -uword64 -convert (SIM_DESC sd, - sim_cpu *cpu, - address_word cia, - int rm, - uword64 op, - FP_formats from, - FP_formats to) -{ - sim_fpu wop; - sim_fpu_round round; - unsigned32 result32; - unsigned64 result64; - -#ifdef DEBUG -#if 0 /* FIXME: doesn't compile */ - printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC)); -#endif -#endif /* DEBUG */ - - switch (rm) - { - case FP_RM_NEAREST: - /* Round result to nearest representable value. When two - representable values are equally near, round to the value - that has a least significant bit of zero (i.e. is even). */ - round = sim_fpu_round_near; - break; - case FP_RM_TOZERO: - /* Round result to the value closest to, and not greater in - magnitude than, the result. */ - round = sim_fpu_round_zero; - break; - case FP_RM_TOPINF: - /* Round result to the value closest to, and not less than, - the result. */ - round = sim_fpu_round_up; - break; - - case FP_RM_TOMINF: - /* Round result to the value closest to, and not greater than, - the result. */ - round = sim_fpu_round_down; - break; - default: - round = 0; - fprintf (stderr, "Bad switch\n"); - abort (); - } - - /* Convert the input to sim_fpu internal format */ - switch (from) - { - case fmt_double: - sim_fpu_64to (&wop, op); - break; - case fmt_single: - sim_fpu_32to (&wop, op); - break; - case fmt_word: - sim_fpu_i32to (&wop, op, round); - break; - case fmt_long: - sim_fpu_i64to (&wop, op, round); - break; - default: - fprintf (stderr, "Bad switch\n"); - abort (); - } - - /* Convert sim_fpu format into the output */ - /* The value WOP is converted to the destination format, rounding - using mode RM. When the destination is a fixed-point format, then - a source value of Infinity, NaN or one which would round to an - integer outside the fixed point range then an IEEE Invalid - Operation condition is raised. */ - switch (to) - { - case fmt_single: - sim_fpu_round_32 (&wop, round, 0); - sim_fpu_to32 (&result32, &wop); - result64 = result32; - break; - case fmt_double: - sim_fpu_round_64 (&wop, round, 0); - sim_fpu_to64 (&result64, &wop); - break; - case fmt_word: - sim_fpu_to32i (&result32, &wop, round); - result64 = result32; - break; - case fmt_long: - sim_fpu_to64i (&result64, &wop, round); - break; - default: - result64 = 0; - fprintf (stderr, "Bad switch\n"); - abort (); - } - -#ifdef DEBUG - printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to)); -#endif /* DEBUG */ - - return(result64); -} - /*-- co-processor support routines ------------------------------------------*/ |