/* Implement a 32/64 bit reciprocal square root, signaling FP exceptions when appropriate. */ void fpu_rsqrt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, const void *reg_in, void *reg_out, const struct fp_prec_t *ops) { sim_fpu in, med, out; REG2VAL (reg_in, &in); ROUND (&in); FPCR &= ~ EC_MASK; switch (sim_fpu_is (&in)) { case SIM_FPU_IS_SNAN: case SIM_FPU_IS_NNUMBER: case SIM_FPU_IS_NINF: if (FPCR & EE_V) FPCR |= EC_V; else VAL2REG (&sim_fpu_qnan, reg_out); break; case SIM_FPU_IS_QNAN: VAL2REG (&sim_fpu_qnan, reg_out); break; case SIM_FPU_IS_PINF: VAL2REG (&sim_fpu_zero, reg_out); break; case SIM_FPU_IS_PNUMBER: { /* Since we don't have a function to compute rsqrt directly, use sqrt and inv. */ sim_fpu_status stat = 0; stat |= sim_fpu_sqrt (&med, &in); stat |= sim_fpu_inv (&out, &med); stat |= ROUND (&out); if (fpu_status_ok (stat)) VAL2REG (&out, reg_out); } break; case SIM_FPU_IS_NZERO: case SIM_FPU_IS_PZERO: if (FPCR & EE_Z) FPCR |= EC_Z; else { /* Generate an INF with the same sign. */ sim_fpu_inv (&out, &in); VAL2REG (&out, reg_out); } break; default: abort (); } fpu_check_signal_exception (sd, cpu, cia); }
SF sh64_fsqrts(SIM_CPU *current_cpu, SF frgh) { SF result; sim_fpu f, fres; sim_fpu_32to (&f, frgh); sim_fpu_sqrt (&fres, &f); sim_fpu_to32 (&result, &fres); return result; }
DF sh64_fsqrtd(SIM_CPU *current_cpu, DF drgh) { DF result; sim_fpu f, fres; sim_fpu_64to (&f, drgh); sim_fpu_sqrt (&fres, &f); sim_fpu_to64 (&result, &fres); return result; }
static DF sqrtdf (CGEN_FPU* fpu, DF x) { sim_fpu op1; sim_fpu ans; unsigned64 res; sim_fpu_status status; sim_fpu_64to (&op1, x); status = sim_fpu_sqrt (&ans, &op1); if (status != 0) (*fpu->ops->error) (fpu, status); sim_fpu_to64 (&res, &ans); return res; }
static SF sqrtsf (CGEN_FPU* fpu, SF x) { sim_fpu op1; sim_fpu ans; unsigned32 res; sim_fpu_status status; sim_fpu_32to (&op1, x); status = sim_fpu_sqrt (&ans, &op1); if (status != 0) (*fpu->ops->error) (fpu, status); sim_fpu_to32 (&res, &ans); return res; }
float32 syst_float32_sqrt( float32 a ) { float32 z; sim_fpu A; sim_fpu ans; sim_fpu_32to (&A, a); #if 0 sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); fprintf (stdout, " sqrt> "); #endif flags |= sim_fpu_sqrt (&ans, &A); #if 0 sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); #endif flags |= sim_fpu_round_32 (&ans, rounding_mode, 0); #if 0 fprintf (stdout, " (%x)\n", flags); #endif sim_fpu_to32 (&z, &ans); return z; }
float64 syst_float64_sqrt( float64 a ) { float64 z; sim_fpu A; sim_fpu ans; sim_fpu_64to (&A, a); #if 0 sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); printf (" sqrt> "); printf ("\n"); #endif flags |= sim_fpu_sqrt (&ans, &A); #if 0 sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); #endif flags |= sim_fpu_round_64 (&ans, rounding_mode, 0); #if 0 sim_fpu_print_status (flags, (sim_fpu_print_func*) fprintf, stdout); fprintf (stdout, "\n"); #endif sim_fpu_to64 (&z, &ans); return z; }