📄 float.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#define Extern extern#include "power.h"ulong setfpscr(void);void setfpcc(double);void farith(ulong);void farith2(ulong);void fariths(ulong);void fcmp(ulong);void mtfsb1(ulong);void mcrfs(ulong);void mtfsb0(ulong);void mtfsf(ulong);void mtfsfi(ulong);void mffs(ulong);void mtfsf(ulong);Inst op59[] = {[18] {fariths, "fdivs", Ifloat},[20] {fariths, "fsubs", Ifloat},[21] {fariths, "fadds", Ifloat},[22] {unimp, "fsqrts", Ifloat},[24] {unimp, "fres", Ifloat},[25] {fariths, "fmuls", Ifloat},[28] {fariths, "fmsubs", Ifloat},[29] {fariths, "fmadds", Ifloat},[30] {fariths, "fnmsubs", Ifloat},[31] {fariths, "fnmadds", Ifloat},};Inset ops59 = {op59, nelem(op59)};Inst op63a[] = {[12] {farith, "frsp", Ifloat},[14] {farith, "fctiw", Ifloat},[15] {farith, "fctiwz", Ifloat},[18] {farith, "fdiv", Ifloat},[20] {farith, "fsub", Ifloat},[21] {farith, "fadd", Ifloat},[22] {unimp, "frsqrt", Ifloat},[23] {unimp, "fsel", Ifloat},[25] {farith, "fmul", Ifloat},[26] {unimp, "frsqrte", Ifloat},[28] {farith, "fmsub", Ifloat},[29] {farith, "fmadd", Ifloat},[30] {farith, "fnmsub", Ifloat},[31] {farith, "fnmadd", Ifloat},};Inset ops63a= {op63a, nelem(op63a)};Inst op63b[] = {[0] {fcmp, "fcmpu", Ifloat},[32] {fcmp, "fcmpo", Ifloat},[38] {mtfsb1, "mtfsb1", Ifloat},[40] {farith2, "fneg", Ifloat},[64] {mcrfs, "mcrfs", Ifloat},[70] {mtfsb0, "mtfsb0", Ifloat},[72] {farith2, "fmr", Ifloat},[134] {mtfsfi, "mtfsfi", Ifloat},[136] {farith2, "fnabs", Ifloat},[264] {farith2, "fabs", Ifloat},[583] {mffs, "mffs", Ifloat},[711] {mtfsf, "mtfsf", Ifloat},};Inset ops63b = {op63b, nelem(op63b)};voidlfs(ulong ir){ ulong ea; int imm, ra, rd, upd; union { ulong i; float f; } u; getairr(ir); ea = imm; upd = (ir&(1L<<26))!=0; if(ra) { ea += reg.r[ra]; if(upd) reg.r[ra] = ea; } else { if(upd) undef(ir); } if(trace) itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea); u.i = getmem_w(ea); reg.fd[rd] = u.f;}voidlfsx(ulong ir){ ulong ea; int rd, ra, rb, upd; union { ulong i; float f; } u; getarrr(ir); ea = reg.r[rb]; upd = ((ir>>1)&0x3FF)==567; if(ra){ ea += reg.r[ra]; if(upd) reg.r[ra] = ea; if(trace) itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea); } else { if(upd) undef(ir); if(trace) itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea); } u.i = getmem_w(ea); reg.fd[rd] = u.f;}voidlfd(ulong ir){ ulong ea; int imm, ra, rd, upd; getairr(ir); ea = imm; upd = (ir&(1L<<26))!=0; if(ra) { ea += reg.r[ra]; if(upd) reg.r[ra] = ea; } else { if(upd) undef(ir); } if(trace) itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea); reg.dv[rd] = getmem_v(ea);}voidlfdx(ulong ir){ ulong ea; int rd, ra, rb, upd; getarrr(ir); ea = reg.r[rb]; upd = ((ir>>1)&0x3FF)==631; if(ra){ ea += reg.r[ra]; if(upd) reg.r[ra] = ea; if(trace) itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea); } else { if(upd) undef(ir); if(trace) itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea); } reg.dv[rd] = getmem_v(ea);}voidstfs(ulong ir){ ulong ea; int imm, ra, rd, upd; union { float f; ulong w; } u; getairr(ir); ea = imm; upd = (ir&(1L<<26))!=0; if(ra) { ea += reg.r[ra]; if(upd) reg.r[ra] = ea; } else { if(upd) undef(ir); } if(trace) itrace("%s\tf%d,%ld(r%d) %lux=%g", ci->name, rd, imm, ra, ea, reg.fd[rd]); u.f = reg.fd[rd]; /* BUG: actual PPC conversion is more subtle than this */ putmem_w(ea, u.w);}voidstfsx(ulong ir){ ulong ea; int rd, ra, rb, upd; union { float f; ulong w; } u; getarrr(ir); ea = reg.r[rb]; upd = getxo(ir)==695; if(ra){ ea += reg.r[ra]; if(upd) reg.r[ra] = ea; if(trace) itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, (float)reg.fd[rd]); } else { if(upd) undef(ir); if(trace) itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, (float)reg.fd[rd]); } u.f = reg.fd[rd]; /* BUG: actual PPC conversion is more subtle than this */ putmem_w(ea, u.w);}voidstfd(ulong ir){ ulong ea; int imm, ra, rd, upd; getairr(ir); ea = imm; upd = (ir&(1L<<26))!=0; if(ra) { ea += reg.r[ra]; if(upd) reg.r[ra] = ea; } else { if(upd) undef(ir); } if(trace) itrace("%s\tf%d,%ld(r%d) %lux=%g", ci->name, rd, imm, ra, ea, reg.fd[rd]); putmem_v(ea, reg.dv[rd]);}voidstfdx(ulong ir){ ulong ea; int rd, ra, rb, upd; getarrr(ir); ea = reg.r[rb]; upd = ((ir>>1)&0x3FF)==759; if(ra){ ea += reg.r[ra]; if(upd) reg.r[ra] = ea; if(trace) itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, reg.fd[rd]); } else { if(upd) undef(ir); if(trace) itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, reg.fd[rd]); } putmem_v(ea, reg.dv[rd]);}voidmcrfs(ulong ir){ ulong rd, ra, rb; static ulong fpscr0[] ={ FPS_FX|FPS_OX, FPS_UX|FPS_ZX|FPS_XX|FPS_VXSNAN, FPS_VXISI|FPS_VXIDI|FPS_VXZDZ|FPS_VXIMZ, FPS_VXVC, 0, FPS_VXCVI, }; getarrr(ir); if(rb || ra&3 || rd&3) undef(ir); ra >>= 2; rd >>= 2; reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, getCR(ra, reg.fpscr)); reg.fpscr &= ~fpscr0[ra]; if(trace) itrace("mcrfs\tcrf%d,crf%d\n", rd, ra);}voidmffs(ulong ir){ int rd, ra, rb; getarrr(ir); if(ra || rb) undef(ir); reg.dv[rd] = ((uvlong)0xFFF8000L<<16)|reg.fpscr; /* it's anyone's guess how CR1 should be set when ir&1 */ reg.cr &= ~mkCR(1, 0xE); /* leave SO, reset others */ if(trace) itrace("mffs%s\tfr%d\n", ir&1?".":"", rd);}voidmtfsb1(ulong ir){ int rd, ra, rb; getarrr(ir); if(ra || rb) undef(ir); reg.fpscr |= (1L << (31-rd)); /* BUG: should set summary bits */ if(ir & 1) reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */ if(trace) itrace("mtfsb1%s\tfr%d\n", ir&1?".":"", rd);}voidmtfsb0(ulong ir){ int rd, ra, rb; getarrr(ir); if(ra || rb) undef(ir); reg.fpscr &= ~(1L << (31-rd)); if(ir & 1) reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */ if(trace) itrace("mtfsb0%s\tfr%d\n", ir&1?".":"", rd);}voidmtfsf(ulong ir){ int fm, rb, i; ulong v; if(ir & ((1L << 25)|(1L << 16))) undef(ir); rb = (ir >> 11) & 0x1F; fm = (ir >> 17) & 0xFF; v = reg.dv[rb]; for(i=0; i<8; i++) if(fm & (1 << (7-i))) reg.fpscr = (reg.fpscr & ~mkCR(i, 0xF)) | mkCR(i, getCR(i, v)); /* BUG: should set FEX and VX `according to the usual rule' */ if(ir & 1) reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */ if(trace) itrace("mtfsf%s\t#%.2x,fr%d", ir&1?".":"", fm, rb);}voidmtfsfi(ulong ir){ int imm, rd; if(ir & ((0x7F << 16)|(1L << 11))) undef(ir); rd = (ir >> 23) & 0xF; imm = (ir >> 12) & 0xF; reg.fpscr = (reg.fpscr & ~mkCR(rd, 0xF)) | mkCR(rd, imm); /* BUG: should set FEX and VX `according to the usual rule' */ if(ir & 1) reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */ if(trace) itrace("mtfsfi%s\tcrf%d,#%x", ir&1?".":"", rd, imm);}voidfcmp(ulong ir){ int fc, rd, ra, rb; getarrr(ir); if(rd & 3) undef(ir); rd >>= 2; SET(fc); switch(getxo(ir)) { default: undef(ir); case 0: if(trace) itrace("fcmpu\tcr%d,f%d,f%d", rd, ra, rb); if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) { fc = CRFU; break; } if(reg.fd[ra] == reg.fd[rb]) { fc = CREQ; break; } if(reg.fd[ra] < reg.fd[rb]) { fc = CRLT; break; } if(reg.fd[ra] > reg.fd[rb]) { fc = CRGT; break; } print("qi: fcmp error\n"); break; case 32: if(trace) itrace("fcmpo\tcr%d,f%d,f%d", rd, ra, rb); if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) { /* BUG: depends whether quiet or signalling ... */ fc = CRFU; Bprint(bioout, "invalid_fp_register\n"); longjmp(errjmp, 0); } if(reg.fd[ra] == reg.fd[rb]) { fc = CREQ; break; } if(reg.fd[ra] < reg.fd[rb]) { fc = CRLT; break; } if(reg.fd[ra] > reg.fd[rb]) { fc = CRGT; break; } print("qi: fcmp error\n"); break; } fc >>= 28; reg.cr = (reg.cr & ~mkCR(rd,~0)) | mkCR(rd, fc); reg.fpscr = (reg.fpscr & ~0xF800) | (fc<<11); /* BUG: update FX, VXSNAN, VXVC */}/* * the farith functions probably don't produce the right results * in the presence of NaNs, Infs, etc., esp. wrt exception handling, */voidfariths(ulong ir){ int rd, ra, rb, rc, fmt; char *cc; ulong fpscr; fmt = 0; rc = (ir>>6)&0x1F; getarrr(ir); switch(getxo(ir)&0x1F) { /* partial XO decode */ default: undef(ir); case 18: if((float)reg.fd[rb] == 0.0) { Bprint(bioout, "fp_exception ZX\n"); reg.fpscr |= FPS_ZX | FPS_FX; longjmp(errjmp, 0); } reg.fd[rd] = (float)(reg.fd[ra] / reg.fd[rb]); break; case 20: reg.fd[rd] = (float)(reg.fd[ra] - reg.fd[rb]); break; case 21: reg.fd[rd] = (float)(reg.fd[ra] + reg.fd[rb]); break; case 25: reg.fd[rd] = (float)(reg.fd[ra] * reg.fd[rc]); rb = rc; break; case 28: reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]); fmt = 2; break; case 29: reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]); fmt = 2; break; case 30: reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]); fmt = 2; break; case 31: reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]); fmt = 2; break; } if(fmt==1 && ra) undef(ir); fpscr = setfpscr(); setfpcc(reg.fd[rd]); cc = ""; if(ir & 1) { cc = "."; reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28)); } if(trace) { switch(fmt) { case 0: itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb); break; case 1: itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb); break; case 2: itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb); break; } }}voidfarith(ulong ir){ vlong vl; int rd, ra, rb, rc, fmt; char *cc; ulong fpscr; int nocc; double d; fmt = 0; nocc = 0; rc = (ir>>6)&0x1F; getarrr(ir); switch(getxo(ir)&0x1F) { /* partial XO decode */ default: undef(ir); case 12: /* frsp */ reg.fd[rd] = (float)reg.fd[rb]; fmt = 1; break; case 14: /* fctiw */ /* BUG: ignores rounding mode */ case 15: /* fctiwz */ d = reg.fd[rb]; if(d >= 0x7fffffff) vl = 0x7fffffff; else if(d < 0x80000000) vl = 0x80000000; else vl = d; reg.dv[rd] = vl; fmt = 1; nocc = 1; break; case 18: if(reg.fd[rb] == 0.0) { Bprint(bioout, "fp_exception ZX\n"); reg.fpscr |= FPS_ZX | FPS_FX; longjmp(errjmp, 0); } reg.fd[rd] = reg.fd[ra] / reg.fd[rb]; break; case 20: reg.fd[rd] = reg.fd[ra] - reg.fd[rb]; break; case 21: reg.fd[rd] = reg.fd[ra] + reg.fd[rb]; break; case 25: reg.fd[rd] = reg.fd[ra] * reg.fd[rc]; rb = rc; break; case 28: reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]; fmt = 2; break; case 29: reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]; fmt = 2; break; case 30: reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]); fmt = 2; break; case 31: reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]); fmt = 2; break; } if(fmt==1 && ra) undef(ir); fpscr = setfpscr(); if(nocc == 0) setfpcc(reg.fd[rd]); cc = ""; if(ir & 1) { cc = "."; reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28)); } if(trace) { switch(fmt) { case 0: itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb); break; case 1: itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb); break; case 2: itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb); break; } }}voidfarith2(ulong ir){ int rd, ra, rb; char *cc; ulong fpscr; getarrr(ir); switch(getxo(ir)) { /* full XO decode */ default: undef(ir); case 40: reg.fd[rd] = -reg.fd[rb]; break; case 72: reg.fd[rd] = reg.fd[rb]; break; case 136: reg.fd[rd] = -fabs(reg.fd[rb]); break; case 264: reg.fd[rd] = fabs(reg.fd[rb]); break; } if(ra) undef(ir); fpscr = setfpscr(); setfpcc(reg.fd[rd]); cc = ""; if(ir & 1) { cc = "."; reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28)); } if(trace) itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);}ulongsetfpscr(void){ ulong fps, fpscr; fps = getfsr(); fpscr = reg.fpscr; if(fps & FPAOVFL) fpscr |= FPS_OX; if(fps & FPAINEX) fpscr |= FPS_XX; if(fps & FPAUNFL) fpscr |= FPS_UX; if(fps & FPAZDIV) fpscr |= FPS_ZX; if(fpscr != reg.fpscr) { fpscr |= FPS_FX; reg.fpscr = fpscr; } return fpscr;}voidsetfpcc(double r){ int c; c = 0; if(r == 0) c |= 2; else if(r < 0) c |= 4; else c |= 8; if(isNaN(r)) c |= 1; reg.fpscr = (reg.fpscr & ~0xF800) | (0<<15) | (c<<11); /* unsure about class bit */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -