Sigrid Haflínudóttirfirst dirty version of the portd7ad0686 years agoHistory
1218 lines · 24.9 KB · C
RawDownload
/*	FPCPEMDV.h 	Copyright (C) 2007 Ross Martin, Paul C. Pratt 	You can redistribute this file and/or modify it under the terms	of version 2 of the GNU General Public License as published by	the Free Software Foundation.  You should have received a copy	of the license along with this file; see the file COPYING. 	This file is distributed in the hope that it will be useful,	but WITHOUT ANY WARRANTY; without even the implied warranty of	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	license for more details.*/ /*	Floating Point CoProcessor Emulated Device	(included by MINEM68K.c)*/ /*	ReportAbnormalID unused 0x0306 - 0x03FF*/  LOCALVAR struct fpustruct{	myfpr fp[8];	CPTR FPIAR; /* Floating point instruction address register */} fpu_dat; LOCALPROC myfp_SetFPIAR(ui5r v){	fpu_dat.FPIAR = v;} LOCALFUNC ui5r myfp_GetFPIAR(void){	return fpu_dat.FPIAR;} LOCALFUNC blnr DecodeAddrModeRegister(ui5b sz){	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;	ui4r themode = (Dat >> 3) & 7;	ui4r thereg = Dat & 7; 	switch (themode) {		case 2 :		case 3 :		case 4 :		case 5 :		case 6 :			return DecodeModeRegister(sz);			break;		case 7 :			switch (thereg) {				case 0 :				case 1 :				case 2 :				case 3 :				case 4 :					return DecodeModeRegister(sz);					break;				default :					return falseblnr;					break;			}			break;		default :			return falseblnr;			break;	}} LOCALPROC read_long_double(ui5r addr, myfpr *r){	ui4r v2;	ui5r v1;	ui5r v0; 	v2 = get_word(addr + 0);	/* ignore word at offset 2 */	v1 = get_long(addr + 4);	v0 = get_long(addr + 8); 	myfp_FromExtendedFormat(r, v2, v1, v0);} LOCALPROC write_long_double(ui5r addr, myfpr *xx){	ui4r v2;	ui5r v1;	ui5r v0; 	myfp_ToExtendedFormat(xx, &v2, &v1, &v0); 	put_word(addr + 0, v2);	put_word(addr + 2,  0);	put_long(addr + 4, v1);	put_long(addr + 8, v0);} LOCALPROC read_double(ui5r addr, myfpr *r){	ui5r v1;	ui5r v0; 	v1 = get_long(addr + 0);	v0 = get_long(addr + 4); 	myfp_FromDoubleFormat(r, v1, v0);} LOCALPROC write_double(ui5r addr, myfpr *dd){	ui5r v1;	ui5r v0; 	myfp_ToDoubleFormat(dd, &v1, &v0); 	put_long(addr + 0, v1);	put_long(addr + 4, v0);} #if 0LOCALPROC read_single(ui5r addr, myfpr *r){	myfp_FromSingleFormat(r, get_long(addr));} LOCALPROC write_single(ui5r addr, myfpr *ff){	put_long(addr, myfp_ToSingleFormat(ff));}#endif  LOCALFUNC int CheckFPCondition(ui4b predicate){	int condition_true = 0; 	ui3r cc = myfp_GetConditionCodeByte(); 	int c_nan  = (cc) & 1;	/* int c_inf  = (cc >> 1) & 1; */	int c_zero = (cc >> 2) & 1;	int c_neg  = (cc >> 3) & 1; 	/*		printf(			"FPSR Checked: c_nan=%d, c_zero=%d, c_neg=%d,"			" predicate=0x%04x\n",			c_nan, c_zero, c_neg, predicate);	*/ 	switch (predicate) {		case 0x11: /* SEQ */		case 0x01: /* EQ */			condition_true = c_zero;			break;		case 0x1E: /* SNE */		case 0x0E: /* NE */			condition_true = ! c_zero;			break;		case 0x02: /* OGT */		case 0x12: /* GT */			condition_true = (! c_neg) && (! c_zero) && (! c_nan);			break;		case 0x0D: /* ULE */		case 0x1D: /* NGT */			condition_true = c_neg || c_zero || c_nan;			break;		case 0x03: /* OGE */		case 0x13: /* GE */			condition_true = c_zero || ((! c_neg) && (! c_nan));			break;		case 0x0C: /* ULT */		case 0x1C: /* NGE */			condition_true = c_nan || ((! c_zero) && c_neg) ;			break;		case 0x04: /* OLT */		case 0x14: /* LT */			condition_true = c_neg && (! c_nan) && (! c_zero);			break;		case 0x0B: /* UGE */		case 0x1B: /* NLT */			condition_true = c_nan || c_zero || (! c_neg);			break;		case 0x05: /* OLE */		case 0x15: /* LE */			condition_true = ((! c_nan) && c_neg) || c_zero;			break;		case 0x0A: /* UGT */		case 0x1A: /* NLE */			condition_true = c_nan || ((! c_neg) && (! c_zero));			break;		case 0x06: /* OGL */		case 0x16: /* GL */			condition_true = (! c_nan) && (! c_zero);			break;		case 0x09: /* UEQ */		case 0x19: /* NGL */			condition_true = c_nan || c_zero;			break;		case 0x07: /* OR */		case 0x17: /* GLE */			condition_true = ! c_nan;			break;		case 0x08: /* NGLE */		case 0x18: /* NGLE */			condition_true = c_nan;			break;		case 0x00: /* SFALSE */		case 0x10: /* FALSE */			condition_true = 0;			break;		case 0x0F: /* STRUE */		case 0x1F: /* TRUE */			condition_true = 1;			break;	} 	/* printf("condition_true=%d\n", condition_true); */ 	return condition_true;} LOCALIPROC DoCodeFPU_dflt(void){	ReportAbnormalID(0x0301,		"unimplemented Floating Point Instruction");#if dbglog_HAVE	{		ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)			| V_regs.CurDecOpY.v[0].ArgDat; 		dbglog_writelnNum("opcode", opcode);	}#endif	DoCodeFdefault();} LOCALIPROC DoCodeFPU_Save(void){	ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)		| V_regs.CurDecOpY.v[0].ArgDat;	if ((opcode == 0xF327) || (opcode == 0xF32D)) {#if 0		DecodeModeRegister(4);		SetArgValueL(0); /* for now, try null state frame */#endif		/* 28 byte 68881 IDLE frame */ 		if (! DecodeAddrModeRegister(28)) {			DoCodeFPU_dflt();#if dbglog_HAVE			dbglog_writeln(				"DecodeAddrModeRegister fails in DoCodeFPU_Save");#endif		} else {			put_long(V_regs.ArgAddr.mem, 0x1f180000);			put_long(V_regs.ArgAddr.mem + 4, 0);			put_long(V_regs.ArgAddr.mem + 8, 0);			put_long(V_regs.ArgAddr.mem + 12, 0);			put_long(V_regs.ArgAddr.mem + 16, 0);			put_long(V_regs.ArgAddr.mem + 20, 0);			put_long(V_regs.ArgAddr.mem + 24, 0x70000000);		} 	} else {		DoCodeFPU_dflt();#if dbglog_HAVE		dbglog_writeln("unimplemented FPU Save");#endif	}} LOCALIPROC DoCodeFPU_Restore(void){	ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)		| V_regs.CurDecOpY.v[0].ArgDat;	ui4r themode = (opcode >> 3) & 7;	ui4r thereg = opcode & 7;	if ((opcode == 0xF35F) || (opcode == 0xF36D)) {		ui5r dstvalue; 		if (! DecodeAddrModeRegister(4)) {			DoCodeFPU_dflt();#if dbglog_HAVE			dbglog_writeln(				"DecodeAddrModeRegister fails in DoCodeFPU_Restore");#endif		} else {			dstvalue = get_long(V_regs.ArgAddr.mem);			if (dstvalue != 0) {				if (0x1f180000 == dstvalue) {					if (3 == themode) {						m68k_areg(thereg) = V_regs.ArgAddr.mem + 28;					}				} else {					DoCodeFPU_dflt();#if dbglog_HAVE					dbglog_writeln("unknown restore");						/* not a null state we saved */#endif				}			}		}	} else {		DoCodeFPU_dflt();#if dbglog_HAVE		dbglog_writeln("unimplemented FPU Restore");#endif	}} LOCALIPROC DoCodeFPU_FBccW(void){	/*		Also get here for a NOP instruction (opcode 0xF280),		which is simply a FBF.w with offset 0	*/	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 	if (CheckFPCondition(Dat & 0x3F)) {		DoCodeBraW();	} else {		SkipiWord();	} 	/* printf("pc_p set to 0x%p in FBcc (32bit)\n", V_pc_p); */} LOCALIPROC DoCodeFPU_FBccL(void){	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 	if (CheckFPCondition(Dat & 0x3F)) {		DoCodeBraL();	} else {		SkipiLong();	}} LOCALIPROC DoCodeFPU_DBcc(void){	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;	ui4r thereg = Dat & 7;	ui4b word2 = (int)nextiword(); 	ui4b predicate = word2 & 0x3F; 	int condition_true = CheckFPCondition(predicate); 	if (! condition_true) {		ui5b fdb_count = ui5r_FromSWord(m68k_dreg(thereg)) - 1; 		m68k_dreg(thereg) =			(m68k_dreg(thereg) & ~ 0xFFFF) | (fdb_count & 0xFFFF);		if ((si5b)fdb_count == -1) {			SkipiWord();		} else {			DoCodeBraW();		}	} else {		SkipiWord();	}} LOCALIPROC DoCodeFPU_Trapcc(void){	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;	ui4r thereg = Dat & 7; 	ui4b word2 = (int)nextiword(); 	ui4b predicate = word2 & 0x3F; 	int condition_true = CheckFPCondition(predicate); 	if (thereg == 2) {		(void) nextiword();	} else if (thereg == 3) {		(void) nextilong();	} else if (thereg == 4) {	} else {		ReportAbnormalID(0x0302, "Invalid FTRAPcc (?");	} 	if (condition_true) {		ReportAbnormalID(0x0303, "FTRAPcc trapping");		Exception(7);	}} LOCALIPROC DoCodeFPU_Scc(void){	ui4b word2 = (int)nextiword(); 	if (! DecodeModeRegister(1)) {		DoCodeFPU_dflt();#if dbglog_HAVE		dbglog_writeln("bad mode/reg in DoCodeFPU_Scc");#endif	} else {		if (CheckFPCondition(word2 & 0x3F)) {			SetArgValueB(0xFFFF);		} else {			SetArgValueB(0x0000);		}	}} LOCALPROC DoCodeF_InvalidPlusWord(void){	BackupPC();	DoCodeFPU_dflt();} LOCALFUNC int CountCSIAlist(ui4b word2){	ui4b regselect = (word2 >> 10) & 0x7;	int num = 0; 	if (regselect & 1) {		num++;	}	if (regselect & 2) {		num++;	}	if (regselect & 4) {		num++;	} 	return num;} LOCALPROC DoCodeFPU_Move_EA_CSIA(ui4b word2){	int n;	ui5b ea_value[3];	ui4b regselect = (word2 >> 10) & 0x7;	int num = CountCSIAlist(word2); 	if (regselect == 0) {		DoCodeF_InvalidPlusWord();#if dbglog_HAVE		dbglog_writeln("Invalid FMOVE instruction");#endif		return;	} 	/* FMOVEM.L <EA>, <FP CR,SR,IAR list> */ 	if (! DecodeModeRegister(4 * num)) {		DoCodeF_InvalidPlusWord();#if dbglog_HAVE		dbglog_writeln("bad mode/reg in DoCodeFPU_Move_EA_CSIA");#endif	} else {		ea_value[0] = GetArgValueL();		if (num > 1) {			ea_value[1] = get_long(V_regs.ArgAddr.mem + 4);		}		if (num > 2) {			ea_value[2] = get_long(V_regs.ArgAddr.mem + 8);		} 		n = 0;		if (regselect & (1 << 2)) {			myfp_SetFPCR(ea_value[n++]);		}		if (regselect & (1 << 1)) {			myfp_SetFPSR(ea_value[n++]);		}		if (regselect & (1 << 0)) {			myfp_SetFPIAR(ea_value[n++]);		}	}} LOCALPROC DoCodeFPU_MoveM_CSIA_EA(ui4b word2){	int n;	ui5b ea_value[3];	int num = CountCSIAlist(word2); 	ui4b regselect = (word2 >> 10) & 0x7; 	/* FMOVEM.L <FP CR,SR,IAR list>, <EA> */ 	if (0 == regselect) {		DoCodeF_InvalidPlusWord();#if dbglog_HAVE		dbglog_writeln("Invalid FMOVE instruction");#endif	} else	if (! DecodeModeRegister(4 * num)) {

Lines 1–500 of 1218.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t