?? reg_ld_str.c
字號:
((long *) &tll)[0] = 0; } else return 0; } else if (t.sign) tll = -tll; REENTRANT_CHECK(OFF);/* verify_area(VERIFY_WRITE, (void *) d, 8); */ suword((unsigned long *) d, ((long *) &tll)[0]); suword(1 + (unsigned long *) d, ((long *) &tll)[1]); REENTRANT_CHECK(ON); return 1;}/* Put a long into user memory */intreg_store_int32(void){ long *d = (long *) FPU_data_address; FPU_REG t; if (FPU_st0_tag == TW_Empty) { /* Empty register (stack underflow) */ EXCEPTION(EX_StackUnder); if (control_word & EX_Invalid) { /* The masked response */ /* Put out the QNaN indefinite */ REENTRANT_CHECK(OFF);/* verify_area(VERIFY_WRITE, d, 4);*/ suword((unsigned long *) d, 0x80000000); REENTRANT_CHECK(ON); return 1; } else return 0; } reg_move(FPU_st0_ptr, &t); round_to_int(&t); if (t.sigh || ((t.sigl & 0x80000000) && !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG)))) { EXCEPTION(EX_Invalid); /* This is a special case: see sec 16.2.5.1 of the 80486 book */ if (control_word & EX_Invalid) { /* Produce "indefinite" */ t.sigl = 0x80000000; } else return 0; } else if (t.sign) t.sigl = -(long) t.sigl; REENTRANT_CHECK(OFF);/* verify_area(VERIFY_WRITE, d, 4); */ suword((unsigned long *) d, t.sigl); REENTRANT_CHECK(ON); return 1;}/* Put a short into user memory */intreg_store_int16(void){ short *d = (short *) FPU_data_address; FPU_REG t; short ts; if (FPU_st0_tag == TW_Empty) { /* Empty register (stack underflow) */ EXCEPTION(EX_StackUnder); if (control_word & EX_Invalid) { /* The masked response */ /* Put out the QNaN indefinite */ REENTRANT_CHECK(OFF);/* verify_area(VERIFY_WRITE, d, 2);*/ susword((unsigned short *) d, 0x8000); REENTRANT_CHECK(ON); return 1; } else return 0; } reg_move(FPU_st0_ptr, &t); round_to_int(&t); if (t.sigh || ((t.sigl & 0xffff8000) && !((t.sigl == 0x8000) && (t.sign == SIGN_NEG)))) { EXCEPTION(EX_Invalid); /* This is a special case: see sec 16.2.5.1 of the 80486 book */ if (control_word & EX_Invalid) { /* Produce "indefinite" */ ts = 0x8000; } else return 0; } else if (t.sign) t.sigl = -t.sigl; REENTRANT_CHECK(OFF);/* verify_area(VERIFY_WRITE, d, 2); */ susword((short *) d, (short) t.sigl); REENTRANT_CHECK(ON); return 1;}/* Put a packed bcd array into user memory */intreg_store_bcd(void){ char *d = (char *) FPU_data_address; FPU_REG t; long long ll; unsigned char b; int i; unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0; if (FPU_st0_tag == TW_Empty) { /* Empty register (stack underflow) */ EXCEPTION(EX_StackUnder); if (control_word & EX_Invalid) { /* The masked response */ /* Put out the QNaN indefinite */ goto put_indefinite; } else return 0; } reg_move(FPU_st0_ptr, &t); round_to_int(&t); ll = *(long long *) (&t.sigl); /* Check for overflow, by comparing with 999999999999999999 decimal. */ if ((t.sigh > 0x0de0b6b3) || ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) { EXCEPTION(EX_Invalid); /* This is a special case: see sec 16.2.5.1 of the 80486 book */ if (control_word & EX_Invalid) { put_indefinite: /* Produce "indefinite" */ REENTRANT_CHECK(OFF);/* verify_area(VERIFY_WRITE, d, 10);*/ subyte((unsigned char *) d + 7, 0xff); subyte((unsigned char *) d + 8, 0xff); subyte((unsigned char *) d + 9, 0xff); REENTRANT_CHECK(ON); return 1; } else return 0; }/* verify_area(VERIFY_WRITE, d, 10);*/ for (i = 0; i < 9; i++) { b = div_small(&ll, 10); b |= (div_small(&ll, 10)) << 4; REENTRANT_CHECK(OFF); subyte((unsigned char *) d + i, b); REENTRANT_CHECK(ON); } REENTRANT_CHECK(OFF); subyte((unsigned char *) d + 9, sign); REENTRANT_CHECK(ON); return 1;}/*===========================================================================*//* r gets mangled such that sig is int, sign: it is NOT normalized *//* The return value (in eax) is zero if the result is exact, if bits are changed due to rounding, truncation, etc, then a non-zero value is returned *//* Overflow is signalled by a non-zero return value (in eax). In the case of overflow, the returned significand always has the the largest possible value *//* The value returned in eax is never actually needed :-) */intround_to_int(FPU_REG * r){ char very_big; unsigned eax; if (r->tag == TW_Zero) { /* Make sure that zero is returned */ *(long long *) &r->sigl = 0; return 0; /* o.k. */ } if (r->exp > EXP_BIAS + 63) { r->sigl = r->sigh = ~0; /* The largest representable number */ return 1; /* overflow */ } eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp); very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */#define half_or_more (eax & 0x80000000)#define frac_part (eax)#define more_than_half ((eax & 0x80000001) == 0x80000001) switch (control_word & CW_RC) { case RC_RND: if (more_than_half /* nearest */ || (half_or_more && (r->sigl & 1))) { /* odd -> even */ if (very_big) return 1; /* overflow */ (*(long long *) (&r->sigl))++; return LOST_UP; } break; case RC_DOWN: if (frac_part && r->sign) { if (very_big) return 1; /* overflow */ (*(long long *) (&r->sigl))++; return LOST_UP; } break; case RC_UP: if (frac_part && !r->sign) { if (very_big) return 1; /* overflow */ (*(long long *) (&r->sigl))++; return LOST_UP; } break; case RC_CHOP: break; } return eax ? LOST_DOWN : 0;}/*===========================================================================*/char *fldenv(void){ char *s = (char *) FPU_data_address; unsigned short tag_word = 0; unsigned char tag; int i; REENTRANT_CHECK(OFF); control_word = fusword((unsigned short *) s); status_word = fusword((unsigned short *) (s + 4)); tag_word = fusword((unsigned short *) (s + 8)); ip_offset = fuword((unsigned long *) (s + 0x0c)); cs_selector = fuword((unsigned long *) (s + 0x10)); data_operand_offset = fuword((unsigned long *) (s + 0x14)); operand_selector = fuword((unsigned long *) (s + 0x18)); REENTRANT_CHECK(ON); top = (status_word >> SW_Top_Shift) & 7; for (i = 0; i < 8; i++) { tag = tag_word & 3; tag_word >>= 2; switch (tag) { case 0: regs[i].tag = TW_Valid; break; case 1: regs[i].tag = TW_Zero; break; case 2: regs[i].tag = TW_NaN; break; case 3: regs[i].tag = TW_Empty; break; } } FPU_data_address = (void *) data_operand_offset; /* We want no net effect */ FPU_entry_eip = ip_offset; /* We want no net effect */ return s + 0x1c;}voidfrstor(void){ int i, stnr; unsigned char tag; unsigned short saved_status, saved_control; char *s = (char *) fldenv(); saved_status = status_word; saved_control = control_word; control_word = 0x037f; /* Mask all interrupts while we load. */ for (i = 0; i < 8; i++) { /* load each register */ FPU_data_address = (void *) (s + i * 10); reg_load_extended(); stnr = (i + top) & 7; tag = regs[stnr].tag; /* derived from the loaded tag word */ reg_move(&FPU_loaded_data, ®s[stnr]); if (tag == TW_NaN) { /* The current data is a special, i.e. NaN, * unsupported, infinity, or denormal */ unsigned char t = regs[stnr].tag; /* derived from the new * data */ if ( /* (t == TW_Valid) || *** */ (t == TW_Zero)) regs[stnr].tag = TW_NaN; } else regs[stnr].tag = tag; } control_word = saved_control; status_word = saved_status; FPU_data_address = (void *) data_operand_offset; /* We want no net effect */}unsigned shorttag_word(void){ unsigned short word = 0; unsigned char tag; int i; for (i = 7; i >= 0; i--) { switch (tag = regs[i].tag) {#if 0 /* TW_Denormal is not used yet, and probably * won't be */ case TW_Denormal:#endif case TW_Valid: if (regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias)) tag = 2; break; case TW_Infinity: case TW_NaN: tag = 2; break; case TW_Empty: tag = 3; break; /* TW_Valid and TW_Zero already have the correct value */ } word <<= 2; word |= tag; } return word;}char *fstenv(void){ char *d = (char *) FPU_data_address;/* verify_area(VERIFY_WRITE, d, 28);*/#if 0 /****/ *(unsigned short *) &cs_selector = fpu_cs; *(unsigned short *) &operand_selector = fpu_os;#endif /****/ REENTRANT_CHECK(OFF); susword((unsigned short *) d, control_word); susword((unsigned short *) (d + 4), (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift)); susword((unsigned short *) (d + 8), tag_word()); suword((unsigned long *) (d + 0x0c), ip_offset); suword((unsigned long *) (d + 0x10), cs_selector); suword((unsigned long *) (d + 0x14), data_operand_offset); suword((unsigned long *) (d + 0x18), operand_selector); REENTRANT_CHECK(ON); return d + 0x1c;}voidfsave(void){ char *d; FPU_REG tmp, *rp; int i; short e; d = fstenv();/* verify_area(VERIFY_WRITE, d, 80);*/ for (i = 0; i < 8; i++) { /* Store each register in the order: st(0), st(1), ... */ rp = ®s[(top + i) & 7]; e = rp->exp - EXP_BIAS + EXTENDED_Ebias; if (rp->tag == TW_Valid) { if (e >= 0x7fff) { /* Overflow to infinity */ REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), 0); suword((unsigned long *) (d + i * 10 + 4), 0); REENTRANT_CHECK(ON); e = 0x7fff; } else if (e <= 0) { if (e > -63) { /* Make a de-normal */ reg_move(rp, &tmp); tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */ round_to_int(&tmp); REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), tmp.sigl); suword((unsigned long *) (d + i * 10 + 4), tmp.sigh); REENTRANT_CHECK(ON); } else { /* Underflow to zero */ REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), 0); suword((unsigned long *) (d + i * 10 + 4), 0); REENTRANT_CHECK(ON); } e = 0; } else { REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), rp->sigl); suword((unsigned long *) (d + i * 10 + 4), rp->sigh); REENTRANT_CHECK(ON); } } else if (rp->tag == TW_Zero) { REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), 0); suword((unsigned long *) (d + i * 10 + 4), 0); REENTRANT_CHECK(ON); e = 0; } else if (rp->tag == TW_Infinity) { REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), 0); suword((unsigned long *) (d + i * 10 + 4), 0x80000000); REENTRANT_CHECK(ON); e = 0x7fff; } else if (rp->tag == TW_NaN) { REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), rp->sigl); suword((unsigned long *) (d + i * 10 + 4), rp->sigh); REENTRANT_CHECK(ON); e = 0x7fff; } else if (rp->tag == TW_Empty) { /* just copy the reg */ REENTRANT_CHECK(OFF); suword((unsigned long *) (d + i * 10), rp->sigl); suword((unsigned long *) (d + i * 10 + 4), rp->sigh); REENTRANT_CHECK(ON); } e |= rp->sign == SIGN_POS ? 0 : 0x8000; REENTRANT_CHECK(OFF); susword((unsigned short *) (d + i * 10 + 8), e); REENTRANT_CHECK(ON); } finit();}/*===========================================================================*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -