702 lines · 12.4 KB · C
RawDownload
#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;

Lines 1–500 of 702.