⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 float.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 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 + -