📄 ppc-instructions
字号:
/* work out addition in low 25 bits of out */ out = EXTRACTED64(*frac_grx, 0, 23) + inc; *frac_grx = INSERTED64(out, 0, 23); if (out & BIT64(64 - 23 - 1 - 1)) { *frac_grx = (BIT64(0) | INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23)); *exp = *exp + 1; } /* frac_grx[24:52] = 0 already */ FPSCR_SET_FR(inc); FPSCR_SET_FI(gbit || rbit || xbit);#void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode int inc = 0; if (round_mode == fpscr_rn_round_to_nearest) { if (*frac64 == 1 && gbit == 1) inc = 1; if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1; if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_pos_infinity) { if (sign == 0 && gbit == 1) inc = 1; if (sign == 0 && rbit == 1) inc = 1; if (sign == 0 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_neg_infinity) { if (sign == 1 && gbit == 1) inc = 1; if (sign == 1 && rbit == 1) inc = 1; if (sign == 1 && xbit == 1) inc = 1; } /* frac[0:64] = frac[0:64} + inc */ *frac += (*frac64 && inc ? 1 : 0); *frac64 = (*frac64 + inc) & 0x1; FPSCR_SET_FR(inc); FPSCR_SET_FI(gbit | rbit | xbit);void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode int carry_out; int inc = 0; int lsb = EXTRACTED64(*frac, 52, 52); int gbit = EXTRACTED64(*frac, 53, 53); int rbit = EXTRACTED64(*frac, 54, 54); int xbit = EXTRACTED64(*frac, 55, 55); if (round_mode == fpscr_rn_round_to_nearest) { if (lsb == 1 && gbit == 1) inc = 1; if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1; if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_pos_infinity) { if (sign == 0 && gbit == 1) inc = 1; if (sign == 0 && rbit == 1) inc = 1; if (sign == 0 && xbit == 1) inc = 1; } if (round_mode == fpscr_rn_round_towards_neg_infinity) { if (sign == 1 && gbit == 1) inc = 1; if (sign == 1 && rbit == 1) inc = 1; if (sign == 1 && xbit == 1) inc = 1; } /* frac//carry_out = frac + inc */ *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1); carry_out = EXTRACTED64(*frac, 0, 0); *frac <<= 1; if (carry_out == 1) *exp = *exp + 1; FPSCR_SET_FR(inc); FPSCR_SET_FI(gbit | rbit | xbit); FPSCR_SET_XX(FPSCR & fpscr_fi);# conversion of FP to integervoid::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision int i; int exp = 0; unsigned64 frac = 0; int frac64 = 0; int gbit = 0; int rbit = 0; int xbit = 0; int sign = EXTRACTED64(frb, 0, 0); /***/ if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0) GOTO(Infinity_Operand); if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0) GOTO(SNaN_Operand); if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1) GOTO(QNaN_Operand); if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand); if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023; if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022; if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */ frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53); frac64 = 0; } if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */ frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53); frac64 = 0; } gbit = 0, rbit = 0, xbit = 0; for (i = 1; i <= 63 - exp; i++) { xbit = rbit | xbit; rbit = gbit; gbit = frac64; frac64 = EXTRACTED64(frac, 63, 63); frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63); } Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode); if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */ frac = ~frac; frac64 ^= 1; frac += (frac64 ? 1 : 0); frac64 = (frac64 + 1) & 0x1; } if (tgt_precision == 32 /* can ignore frac64 in compare */ && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/) GOTO(Large_Operand); if (tgt_precision == 64 /* can ignore frac64 in compare */ && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/) GOTO(Large_Operand); if (tgt_precision == 32 /* can ignore frac64 in compare */ && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/) GOTO(Large_Operand); if (tgt_precision == 64 /* can ignore frac64 in compare */ && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/) GOTO(Large_Operand); FPSCR_SET_XX(FPSCR & fpscr_fi); if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64; if (tgt_precision == 64) *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64; /*FPSCR[fprf] = undefined */ GOTO(Done); /**/ LABEL(Infinity_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) { if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF; if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000; } else { if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/ if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/ } /* FPSCR[FPRF] = undefined */ } GOTO(Done); /**/ LABEL(SNaN_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000; if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/ /* FPSCR[fprf] = undefined */ } GOTO(Done); /**/ LABEL(QNaN_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000; if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/ /* FPSCR[fprf] = undefined */ } GOTO(Done); /**/ LABEL(Large_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); if ((FPSCR & fpscr_ve) == 0) { if (tgt_precision == 32) { if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff; if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000; } else { if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/ if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/ } /* FPSCR[fprf] = undefined */ } /**/ LABEL(Done):;# extract out raw fields of a FP numberint::function::sign:unsigned64 FRS return (MASKED64(FRS, 0, 0) ? -1 : 1);int::function::biased_exp:unsigned64 frs, int single if (single) return EXTRACTED64(frs, 1, 8); else return EXTRACTED64(frs, 1, 11);unsigned64::function::fraction:unsigned64 frs, int single if (single) return EXTRACTED64(frs, 9, 31); else return EXTRACTED64(frs, 12, 63);# a number?, each of the below return +1 or -1 (based on sign bit)# if true.int::function::is_nor:unsigned64 frs, int single int exp = biased_exp(frs, single); return (exp >= 1 && exp <= (single ? 254 : 2046));int::function::is_zero:unsigned64 FRS return (MASKED64(FRS, 1, 63) == 0 ? sign(FRS) : 0);int::function::is_den:unsigned64 frs, int single int exp = biased_exp(frs, single); unsigned64 frac = fraction(frs, single); return (exp == 0 && frac != 0 ? sign(frs) : 0);int::function::is_inf:unsigned64 frs, int single int exp = biased_exp(frs, single); unsigned64 frac = fraction(frs, single); return (exp == (single ? 255 : 2047) && frac == 0 ? sign(frs) : 0);int::function::is_NaN:unsigned64 frs, int single int exp = biased_exp(frs, single); unsigned64 frac = fraction(frs, single); return (exp == (single ? 255 : 2047) && frac != 0 ? sign(frs) : 0);int::function::is_SNaN:unsigned64 frs, int single return (is_NaN(frs, single) && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12))) ? sign(frs) : 0);int::function::is_QNaN:unsigned64 frs, int single return (is_NaN(frs, single) && !is_SNaN(frs, single));int::function::is_less_than:unsigned64 *fra, unsigned64 *frb return *(double*)fra < *(double*)frb;int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb return *(double*)fra > *(double*)frb;int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb return *(double*)fra == *(double*)frb;# which quiet nan should become the resultunsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single unsigned64 frt = 0; if (is_NaN(fra, single)) frt = fra; else if (is_NaN(frb, single)) if (instruction_is_frsp) frt = MASKED64(frb, 0, 34); else frt = frb; else if (is_NaN(frc, single)) frt = frc; else if (generate_qnan) frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */ else error("select_qnan - default reached\n"); return frt;# detect invalid operationint::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate int fail = 0; if ((check & fpscr_vxsnan) && (is_SNaN(fra, single) || is_SNaN(frb, single))) { FPSCR_OR_VX(fpscr_vxsnan); fail = 1; } if ((check & fpscr_vxisi) && (is_inf(fra, single) && is_inf(frb, single)) && ((negate && sign(fra) != sign(frb)) || (!negate && sign(fra) == sign(frb)))) { /*FIXME: don't handle inf-inf VS inf+-inf */ FPSCR_OR_VX(fpscr_vxisi); fail = 1; } if ((check & fpscr_vxidi) && (is_inf(fra, single) && is_inf(frb, single))) { FPSCR_OR_VX(fpscr_vxidi); fail = 1; } if ((check & fpscr_vxzdz) && (is_zero(fra) && is_zero(frb))) { FPSCR_OR_VX(fpscr_vxzdz); fail = 1; } if ((check & fpscr_vximz) && (is_zero(fra) && is_inf(frb, single))) { FPSCR_OR_VX(fpscr_vximz); fail = 1; } if ((check & fpscr_vxvc) && (is_NaN(fra, single) || is_NaN(frb, single))) { FPSCR_OR_VX(fpscr_vxvc); fail = 1; } if ((check & fpscr_vxsoft)) { FPSCR_OR_VX(fpscr_vxsoft); fail = 1; } if ((check & fpscr_vxsqrt) && sign(fra) < 0) { FPSCR_OR_VX(fpscr_vxsqrt); fail = 1; } /* if ((check && fpscr_vxcvi) { && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single))) FPSCR_OR_VX(fpscr_vxcvi); fail = 1; } */ return fail;# handle case of invalid operationvoid::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int instruction_is_convert_to_64bit, int instruction_is_convert_to_32bit, int single if (FPSCR & fpscr_ve) { /* invalid operation exception enabled */ /* FRT unchaged */ FPSCR_SET_FR(0); FPSCR_SET_FI(0); /* fpscr_FPRF unchanged */ } else { /* invalid operation exception disabled */ if (instruction_is_convert_to_64bit) { error("oopsi"); } else if (instruction_is_convert_to_32bit) { error("oopsi"); } else { /* arrith, frsp */ *frt = select_qnan(fra, frb, frc, instruction_is_frsp, 1/*generate*/, single); FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_SET_FPRF(fpscr_rf_quiet_nan); } }# detect divide by zeroint::function::is_invalid_zero_divide:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, int single int fail = 0; if (is_zero (frb)) { FPSCR_SET_ZX (1); fail = 1; } return fail;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -