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

📄 exec.c

📁 leon2的指令模拟器。leon是应用于航天领域的一款高可靠性的sparc v7指令集的处理器。
💻 C
📖 第 1 页 / 共 3 页
字号:
	    }	    if (address & 0x3) {		sregs->trap = TRAP_UNALI;		break;	    }	    mexc = memory_read(asi, address, &data, 2, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    } else {		sregs->fsr =		    (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);		set_fsr(sregs->fsr);	    }	    break;	case STFSR:	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;		break;	    }	    if (address & 0x3) {		sregs->trap = TRAP_UNALI;		break;	    }	    if (ebase.simtime < sregs->ftime) {		sregs->fhold += (sregs->ftime - ebase.simtime);	    }	    mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    }	    break;	case STA:	    if (!chk_asi(sregs, &asi, op3)) break;	case ST:	    if (address & 0x3) {		sregs->trap = TRAP_UNALI;		break;	    }	    mexc = memory_write(asi, address, rdd, 2, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    }	    break;	case STBA:	    if (!chk_asi(sregs, &asi, op3)) break;	case STB:	    mexc = memory_write(asi, address, rdd, 0, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    }	    break;	case STDA:	    if (!chk_asi(sregs, &asi, op3)) break;	case STD:	    if (address & 0x7) {		sregs->trap = TRAP_UNALI;		break;	    }	    if (rd & 1) {		rd &= 0x1e;		if (rd > 7)		    rdd = &(sregs->r[(cwp + rd) & 0x7f]);		else		    rdd = &(sregs->g[rd]);	    }	    mexc = memory_write(asi, address, rdd, 3, &ws);	    sregs->hold += ws;	    sregs->icnt = T_STD;#ifdef STAT	    sregs->nstore++;	/* Double store counts twice */#endif	    if (mexc) {		sregs->trap = TRAP_DEXC;		break;	    }	    break;	case STDFQ:	    if ((sregs->psr & 0x1f) > 7) {		sregs->trap = TRAP_UNIMP;		break;	    }	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;		break;	    }	    if (address & 0x7) {		sregs->trap = TRAP_UNALI;		break;	    }	    if (!(sregs->fsr & FSR_QNE)) {		sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;		break;	    }	    rdd = &(sregs->fpq[0]);	    mexc = memory_write(asi, address, rdd, 3, &ws);	    sregs->hold += ws;	    sregs->icnt = T_STD;#ifdef STAT	    sregs->nstore++;	/* Double store counts twice */#endif	    if (mexc) {		sregs->trap = TRAP_DEXC;		break;	    } else {		sregs->fsr &= ~FSR_QNE;		sregs->fpstate = FP_EXE_MODE;	    }	    break;	case STHA:	    if (!chk_asi(sregs, &asi, op3)) break;	case STH:	    if (address & 0x1) {		sregs->trap = TRAP_UNALI;		break;	    }	    mexc = memory_write(asi, address, rdd, 1, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    }	    break;	case STF:	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;		break;	    }	    if (address & 0x3) {		sregs->trap = TRAP_UNALI;		break;	    }	    if (ebase.simtime < sregs->ftime) {		if (sregs->frd == rd)		    sregs->fhold += (sregs->ftime - ebase.simtime);	    }	    mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    }	    break;	case STDF:	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;		break;	    }	    if (address & 0x7) {		sregs->trap = TRAP_UNALI;		break;	    }	    rd &= 0x1E;	    if (ebase.simtime < sregs->ftime) {		if ((sregs->frd == rd) || (sregs->frd + 1 == rd))		    sregs->fhold += (sregs->ftime - ebase.simtime);	    }	    mexc = memory_write(asi, address, &sregs->fsi[rd], 3, &ws);	    sregs->hold += ws;	    sregs->icnt = T_STD;#ifdef STAT	    sregs->nstore++;	/* Double store counts twice */#endif	    if (mexc) {		sregs->trap = TRAP_DEXC;	    }	    break;	case SWAPA:	    if (!chk_asi(sregs, &asi, op3)) break;	case SWAP:	    if (address & 0x3) {		sregs->trap = TRAP_UNALI;		break;	    }	    mexc = memory_read(asi, address, &data, 2, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;		break;	    }	    mexc = memory_write(asi, address, rdd, 2, &ws);	    sregs->hold += ws;	    sregs->icnt = T_LDST;	    if (mexc) {		sregs->trap = TRAP_DEXC;		break;	    } else		*rdd = data;#ifdef STAT	    sregs->nload++;#endif	    break;	default:	    sregs->trap = TRAP_UNIMP;	    break;	}#ifdef LOAD_DEL	if (!(op3 & 4)) {	    sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt;	    sregs->ildreg = rd;	    if ((op3 | 0x10) == 0x13)		sregs->ildreg |= 1;	/* Double load, odd register loaded					 * last */	}#endif	break;    default:	sregs->trap = TRAP_UNIMP;	break;    }    sregs->g[0] = 0;    if (!sregs->trap) {	sregs->pc = pc;	sregs->npc = npc;    }    return (0);}#define T_FABSs		2#define T_FADDs		4#define T_FADDd		4#define T_FCMPs		4#define T_FCMPd		4#define T_FDIVs		20#define T_FDIVd		35#define T_FMOVs		2#define T_FMULs		5#define T_FMULd		9#define T_FNEGs		2#define T_FSQRTs	37#define T_FSQRTd	65#define T_FSUBs		4#define T_FSUBd		4#define T_FdTOi		7#define T_FdTOs		3#define T_FiTOs		6#define T_FiTOd		6#define T_FsTOi		6#define T_FsTOd		2#define FABSs	0x09#define FADDs	0x41#define FADDd	0x42#define FCMPs	0x51#define FCMPd	0x52#define FCMPEs	0x55#define FCMPEd	0x56#define FDIVs	0x4D#define FDIVd	0x4E#define FMOVs	0x01#define FMULs	0x49#define FMULd	0x4A#define FNEGs	0x05#define FSQRTs	0x29#define FSQRTd	0x2A#define FSUBs	0x45#define FSUBd	0x46#define FdTOi	0xD2#define FdTOs	0xC6#define FiTOs	0xC4#define FiTOd	0xC8#define FsTOi	0xD1#define FsTOd	0xC9static intfpexec(op3, rd, rs1, rs2, sregs)    uint32          op3, rd, rs1, rs2;    struct pstate  *sregs;{    uint32          opf, tem, accex;    int32           fcc;    uint32          ldadj;    if (sregs->fpstate == FP_EXC_MODE) {	sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;	sregs->fpstate = FP_EXC_PE;	return (0);    }    if (sregs->fpstate == FP_EXC_PE) {	sregs->fpstate = FP_EXC_MODE;	return (TRAP_FPEXC);    }    opf = (sregs->inst >> 5) & 0x1ff;    /*     * Check if we already have an FPop in the pipe. If so, halt until it is     * finished by incrementing fhold with the remaining execution time     */    if (ebase.simtime < sregs->ftime) {	sregs->fhold = (sregs->ftime - ebase.simtime);    } else {	sregs->fhold = 0;	/* Check load dependencies. */	if (ebase.simtime < sregs->ltime) {	    /* Don't check rs1 if single operand instructions */	    if (((opf >> 6) == 0) || ((opf >> 6) == 3))		rs1 = 32;	    /* Adjust for double floats */	    ldadj = opf & 1;	    if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))		sregs->fhold++;	}    }    sregs->finst++;    sregs->frs1 = rs1;		/* Store src and dst for dependecy check */    sregs->frs2 = rs2;    sregs->frd = rd;    sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;    /* SPARC is big-endian - swap double floats if host is little-endian */    /* This is ugly - I know ... */    /* FIXME: should use (CURRENT_HOST_BYTE_ORDER == CURRENT_TARGET_BYTE_ORDER)       but what about machines where float values are different endianness       from integer values? */#ifdef HOST_LITTLE_ENDIAN_FLOAT    rs1 &= 0x1f;    switch (opf) {	case FADDd:	case FDIVd:	case FMULd:	case FSQRTd:	case FSUBd:        case FCMPd:        case FCMPEd:	case FdTOi:	case FdTOs:    	    sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1];    	    sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1];    	    sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];    	    sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];    default:      ;    }#endif    clear_accex();    switch (opf) {    case FABSs:	sregs->fs[rd] = fabs(sregs->fs[rs2]);	sregs->ftime += T_FABSs;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FADDs:	sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2];	sregs->ftime += T_FADDs;	break;    case FADDd:	sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1];	sregs->ftime += T_FADDd;	break;    case FCMPs:    case FCMPEs:	if (sregs->fs[rs1] == sregs->fs[rs2])	    fcc = 3;	else if (sregs->fs[rs1] < sregs->fs[rs2])	    fcc = 2;	else if (sregs->fs[rs1] > sregs->fs[rs2])	    fcc = 1;	else	    fcc = 0;	sregs->fsr |= 0x0C00;	sregs->fsr &= ~(fcc << 10);	sregs->ftime += T_FCMPs;	sregs->frd = 32;	/* rd ignored */	if ((fcc == 0) && (opf == FCMPEs)) {	    sregs->fpstate = FP_EXC_PE;	    sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14);	}	break;    case FCMPd:    case FCMPEd:	if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1])	    fcc = 3;	else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1])	    fcc = 2;	else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1])	    fcc = 1;	else	    fcc = 0;	sregs->fsr |= 0x0C00;	sregs->fsr &= ~(fcc << 10);	sregs->ftime += T_FCMPd;	sregs->frd = 32;	/* rd ignored */	if ((fcc == 0) && (opf == FCMPEd)) {	    sregs->fpstate = FP_EXC_PE;	    sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;	}	break;    case FDIVs:	sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2];	sregs->ftime += T_FDIVs;	break;    case FDIVd:	sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1];	sregs->ftime += T_FDIVd;	break;    case FMOVs:	sregs->fs[rd] = sregs->fs[rs2];	sregs->ftime += T_FMOVs;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FMULs:	sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];	sregs->ftime += T_FMULs;	break;    case FMULd:	sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];	sregs->ftime += T_FMULd;	break;    case FNEGs:	sregs->fs[rd] = -sregs->fs[rs2];	sregs->ftime += T_FNEGs;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FSQRTs:	if (sregs->fs[rs2] < 0.0) {	    sregs->fpstate = FP_EXC_PE;	    sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;	    sregs->fsr = (sregs->fsr & 0x1f) | 0x10;	    break;	}	sregs->fs[rd] = sqrt(sregs->fs[rs2]);	sregs->ftime += T_FSQRTs;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FSQRTd:	if (sregs->fd[rs2 >> 1] < 0.0) {	    sregs->fpstate = FP_EXC_PE;	    sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;	    sregs->fsr = (sregs->fsr & 0x1f) | 0x10;	    break;	}	sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]);	sregs->ftime += T_FSQRTd;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FSUBs:	sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2];	sregs->ftime += T_FSUBs;	break;    case FSUBd:	sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1];	sregs->ftime += T_FSUBd;	break;    case FdTOi:	sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1];	sregs->ftime += T_FdTOi;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FdTOs:	sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1];	sregs->ftime += T_FdTOs;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FiTOs:	sregs->fs[rd] = (float32) sregs->fsi[rs2];	sregs->ftime += T_FiTOs;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FiTOd:	sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2];	sregs->ftime += T_FiTOd;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FsTOi:	sregs->fsi[rd] = (int) sregs->fs[rs2];	sregs->ftime += T_FsTOi;	sregs->frs1 = 32;	/* rs1 ignored */	break;    case FsTOd:	sregs->fd[rd >> 1] = sregs->fs[rs2];	sregs->ftime += T_FsTOd;	sregs->frs1 = 32;	/* rs1 ignored */	break;    default:	sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;	sregs->fpstate = FP_EXC_PE;    }#ifdef ERRINJ    if (errftt) {	sregs->fsr = (sregs->fsr & ~FSR_TT) | (errftt << 14);	sregs->fpstate = FP_EXC_PE;	if (sis_verbose) printf("Inserted fpu error %X\n",errftt);	errftt = 0;    }#endif    accex = get_accex();#ifdef HOST_LITTLE_ENDIAN_FLOAT    switch (opf) {    case FADDd:    case FDIVd:    case FMULd:    case FSQRTd:    case FSUBd:    case FiTOd:    case FsTOd:	sregs->fs[rd & ~1] = sregs->fdp[rd | 1];	sregs->fs[rd | 1] = sregs->fdp[rd & ~1];    default:      ;    }#endif    if (sregs->fpstate == FP_EXC_PE) {	sregs->fpq[0] = sregs->pc;	sregs->fpq[1] = sregs->inst;	sregs->fsr |= FSR_QNE;    } else {	tem = (sregs->fsr >> 23) & 0x1f;	if (tem & accex) {	    sregs->fpstate = FP_EXC_PE;	    sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;	    sregs->fsr = ((sregs->fsr & ~0x1f) | accex);	} else {	    sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex);	}	if (sregs->fpstate == FP_EXC_PE) {	    sregs->fpq[0] = sregs->pc;	    sregs->fpq[1] = sregs->inst;	    sregs->fsr |= FSR_QNE;	}    }    clear_accex();    return (0);}static intchk_asi(sregs, asi, op3)    struct pstate  *sregs;    uint32 *asi, op3;{    if (!(sregs->psr & PSR_S)) {	sregs->trap = TRAP_PRIVI;	return (0);    } else if (sregs->inst & INST_I) {	sregs->trap = TRAP_UNIMP;	return (0);    } else	*asi = (sregs->inst >> 5) & 0x0ff;    return(1);}intexecute_trap(sregs)    struct pstate  *sregs;{    int32           cwp;    if (sregs->trap == 256) {	sregs->pc = 0;	sregs->npc = 4;	sregs->trap = 0;    } else if (sregs->trap == 257) {	    return (ERROR);    } else {	if ((sregs->psr & PSR_ET) == 0)	    return (ERROR);	sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4);	sregs->trap = 0;	sregs->psr &= ~PSR_ET;	sregs->psr |= ((sregs->psr & PSR_S) >> 1);	sregs->annul = 0;	sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP);	cwp = ((sregs->psr & PSR_CWP) << 4);	sregs->r[(cwp + 17) & 0x7f] = sregs->pc;	sregs->r[(cwp + 18) & 0x7f] = sregs->npc;	sregs->psr |= PSR_S;	sregs->pc = sregs->tbr;	sregs->npc = sregs->tbr + 4;        if ( 0 != (1 & sregs->asr17) ) {            /* single vector trapping! */            sregs->pc = sregs->tbr & 0xfffff000;            sregs->npc = sregs->pc + 4;        }	/* Increase simulator time */	sregs->icnt = TRAP_C;    }    return (0);}extern struct irqcell irqarr[16];intcheck_interrupts(sregs)    struct pstate  *sregs;{#ifdef ERRINJ    if (errtt) {	sregs->trap = errtt;	if (sis_verbose) printf("Inserted error trap 0x%02X\n",errtt);	errtt = 0;    }#endif    if ((ext_irl) && (sregs->psr & PSR_ET) &&	((ext_irl == 15) || (ext_irl > (int) ((sregs->psr & PSR_PIL) >> 8)))) {	if (sregs->trap == 0) {	    sregs->trap = 16 + ext_irl;	    irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg);	    return(1);	}    }    return(0);}voidinit_regs(sregs)    struct pstate  *sregs;{    sregs->pc = 0;    sregs->npc = 4;    sregs->trap = 0;    sregs->psr &= 0x00f03fdf;    sregs->psr |= 0x080;	/* Set supervisor bit */    sregs->breakpoint = 0;    sregs->annul = 0;    sregs->fpstate = FP_EXE_MODE;    sregs->fpqn = 0;    sregs->ftime = 0;    sregs->ltime = 0;    sregs->err_mode = 0;    ext_irl = 0;    sregs->g[0] = 0;#ifdef HOST_LITTLE_ENDIAN_FLOAT    sregs->fdp = (float32 *) sregs->fd;    sregs->fsi = (int32 *) sregs->fs;#else    sregs->fs = (float32 *) sregs->fd;    sregs->fsi = (int32 *) sregs->fd;#endif    sregs->fsr = 0;    sregs->fpu_pres = !nfp;    set_fsr(sregs->fsr);    sregs->bphit = 0;    sregs->ildreg = 0;    sregs->ildtime = 0;    sregs->y = 0;    sregs->asr17 = 0;    sregs->rett_err = 0;    sregs->jmpltime = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -