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

📄 exec.c

📁 leon2的指令模拟器。leon是应用于航天领域的一款高可靠性的sparc v7指令集的处理器。
💻 C
📖 第 1 页 / 共 3 页
字号:
		     << 10) | (rs1 >> 1);		if ((sregs->y & 1) == 0)		    operand2 = 0;		*rdd = operand1 + operand2;		sregs->y = (rs1 << 31) | (sregs->y >> 1);		sregs->psr = add_cc(sregs->psr, operand1, operand2, *rdd);		break;	    case DIVScc:		{		  int sign;		  uint32 result, remainder;		  int c0, y31;		  if (!sparclite) {		     sregs->trap = TRAP_UNIMP;                     break;		  }		  sign = ((sregs->psr & PSR_V) != 0) ^ ((sregs->psr & PSR_N) != 0);		  remainder = (sregs->y << 1) | (rs1 >> 31);		  /* If true sign is positive, calculate remainder - divisor.		     Otherwise, calculate remainder + divisor.  */		  if (sign == 0)		    operand2 = ~operand2 + 1;		  result = remainder + operand2;		  /* The SPARClite User's Manual is not clear on how		     the "carry out" of the above ALU operation is to		     be calculated.  From trial and error tests		     on the the chip itself, it appears that it is		     a normal addition carry, and not a subtraction borrow,		     even in cases where the divisor is subtracted		     from the remainder.  FIXME: get the true story		     from Fujitsu. */		  c0 = result < (uint32) remainder		       || result < (uint32) operand2;		  if (result & 0x80000000)		    sregs->psr |= PSR_N;		  else		    sregs->psr &= ~PSR_N;		  y31 = (sregs->y & 0x80000000) == 0x80000000;		  if (result == 0 && sign == y31)		    sregs->psr |= PSR_Z;		  else		    sregs->psr &= ~PSR_Z;		  sign = (sign && !y31) || (!c0 && (sign || !y31));		  if (sign ^ (result >> 31))		    sregs->psr |= PSR_V;		  else		    sregs->psr &= ~PSR_V;		  if (!sign)		    sregs->psr |= PSR_C;		  else		    sregs->psr &= ~PSR_C;		  sregs->y = result;		  if (rd != 0)		    *rdd = (rs1 << 1) | !sign;		}		break;	    case SMUL:		{		  mul64 (rs1, operand2, &sregs->y, rdd, 1);		}		break;	    case SMULCC:		{		  uint32 result;		  mul64 (rs1, operand2, &sregs->y, &result, 1);		  if (result & 0x80000000)		    sregs->psr |= PSR_N;		  else		    sregs->psr &= ~PSR_N;		  if (result == 0)		    sregs->psr |= PSR_Z;		  else		    sregs->psr &= ~PSR_Z;		  *rdd = result;		}		break;	    case UMUL:		{		  mul64 (rs1, operand2, &sregs->y, rdd, 0);		}		break;	    case UMULCC:		{		  uint32 result;		  mul64 (rs1, operand2, &sregs->y, &result, 0);		  if (result & 0x80000000)		    sregs->psr |= PSR_N;		  else		    sregs->psr &= ~PSR_N;		  if (result == 0)		    sregs->psr |= PSR_Z;		  else		    sregs->psr &= ~PSR_Z;		  *rdd = result;		}		break;	    case SDIV:		{		  if (sparclite) {		     sregs->trap = TRAP_UNIMP;                     break;		  }		  if (operand2 == 0) {		    sregs->trap = TRAP_DIV0;		    break;		  }		  div64 (sregs->y, rs1, operand2, rdd, 1);		}		break;	    case SDIVCC:		{		  uint32 result;		  if (sparclite) {		     sregs->trap = TRAP_UNIMP;                     break;		  }		  if (operand2 == 0) {		    sregs->trap = TRAP_DIV0;		    break;		  }		  div64 (sregs->y, rs1, operand2, &result, 1);		  if (result & 0x80000000)		    sregs->psr |= PSR_N;		  else		    sregs->psr &= ~PSR_N;		  if (result == 0)		    sregs->psr |= PSR_Z;		  else		    sregs->psr &= ~PSR_Z;		  /* FIXME: should set overflow flag correctly.  */		  sregs->psr &= ~(PSR_C | PSR_V);		  *rdd = result;		}		break;	    case UDIV:		{		  if (sparclite) {		     sregs->trap = TRAP_UNIMP;                     break;		  }		  if (operand2 == 0) {		    sregs->trap = TRAP_DIV0;		    break;		  }		  div64 (sregs->y, rs1, operand2, rdd, 0);		}		break;	    case UDIVCC:		{		  uint32 result;		  if (sparclite) {		     sregs->trap = TRAP_UNIMP;                     break;		  }		  if (operand2 == 0) {		    sregs->trap = TRAP_DIV0;		    break;		  }		  div64 (sregs->y, rs1, operand2, &result, 0);		  if (result & 0x80000000)		    sregs->psr |= PSR_N;		  else		    sregs->psr &= ~PSR_N;		  if (result == 0)		    sregs->psr |= PSR_Z;		  else		    sregs->psr &= ~PSR_Z;		  /* FIXME: should set overflow flag correctly.  */		  sregs->psr &= ~(PSR_C | PSR_V);		  *rdd = result;		}		break;	    case IXNOR:		*rdd = rs1 ^ ~operand2;		break;	    case IXNORCC:		*rdd = rs1 ^ ~operand2;		log_cc(*rdd, sregs);		break;	    case IXOR:		*rdd = rs1 ^ operand2;		break;	    case IXORCC:		*rdd = rs1 ^ operand2;		log_cc(*rdd, sregs);		break;	    case IOR:		*rdd = rs1 | operand2;		break;	    case IORCC:		*rdd = rs1 | operand2;		log_cc(*rdd, sregs);		break;	    case IORN:		*rdd = rs1 | ~operand2;		break;	    case IORNCC:		*rdd = rs1 | ~operand2;		log_cc(*rdd, sregs);		break;	    case IANDNCC:		*rdd = rs1 & ~operand2;		log_cc(*rdd, sregs);		break;	    case IANDN:		*rdd = rs1 & ~operand2;		break;	    case IAND:		*rdd = rs1 & operand2;		break;	    case IANDCC:		*rdd = rs1 & operand2;		log_cc(*rdd, sregs);		break;	    case SUB:		*rdd = rs1 - operand2;		break;	    case SUBCC:		*rdd = rs1 - operand2;		sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);		break;	    case SUBX:		*rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);		break;	    case SUBXCC:		*rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);		sregs->psr = sub_cc(sregs->psr, rs1, operand2, *rdd);		break;	    case ADD:		*rdd = rs1 + operand2;		break;	    case ADDCC:		*rdd = rs1 + operand2;		sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);		break;	    case ADDX:		*rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);		break;	    case ADDXCC:		*rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);		sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);		break;	    case TADDCC:		*rdd = rs1 + operand2;		sregs->psr = add_cc(sregs->psr, rs1, operand2, *rdd);		if ((rs1 | operand2) & 0x3)		    sregs->psr |= PSR_V;		break;	    case TSUBCC:		*rdd = rs1 - operand2;		sregs->psr = sub_cc (sregs->psr, rs1, operand2, *rdd);		if ((rs1 | operand2) & 0x3)		    sregs->psr |= PSR_V;		break;	    case TADDCCTV:		*rdd = rs1 + operand2;		result = add_cc(0, rs1, operand2, *rdd);		if ((rs1 | operand2) & 0x3)		    result |= PSR_V;		if (result & PSR_V) {		    sregs->trap = TRAP_TAG;		} else {		    sregs->psr = (sregs->psr & ~PSR_CC) | result;		}		break;	    case TSUBCCTV:		*rdd = rs1 - operand2;		result = add_cc (0, rs1, operand2, *rdd);		if ((rs1 | operand2) & 0x3)		    result |= PSR_V;		if (result & PSR_V)		  {		      sregs->trap = TRAP_TAG;		  }		else		  {		      sregs->psr = (sregs->psr & ~PSR_CC) | result;		  }		break;	    case SLL:		*rdd = rs1 << (operand2 & 0x1f);		break;	    case SRL:		*rdd = rs1 >> (operand2 & 0x1f);		break;	    case SRA:		*rdd = ((int) rs1) >> (operand2 & 0x1f);		break;	    case FLUSH:		if (ift) sregs->trap = TRAP_UNIMP;		break;	    case SAVE:		new_cwp = ((sregs->psr & PSR_CWP) - 1) & PSR_CWP;		if (sregs->wim & (1 << new_cwp)) {		    sregs->trap = TRAP_WOFL;		    break;		}		if (rd > 7)		    rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);		*rdd = rs1 + operand2;		sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;		break;	    case RESTORE:		new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;		if (sregs->wim & (1 << new_cwp)) {		    sregs->trap = TRAP_WUFL;		    break;		}		if (rd > 7)		    rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);		*rdd = rs1 + operand2;		sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;		break;	    case RDPSR:		if (!(sregs->psr & PSR_S)) {		    sregs->trap = TRAP_PRIVI;		    break;		}		*rdd = sregs->psr;		break;	    case RDY:                if (!sparclite)                    *rdd = sregs->y;                else {                    int rs1_is_asr = (sregs->inst >> 14) & 0x1f;                    if ( 0 == rs1_is_asr )                        *rdd = sregs->y;                    else if ( 17 == rs1_is_asr )                        *rdd = sregs->asr17;                    else {                        sregs->trap = TRAP_UNIMP;                        break;                    }                }		break;	    case RDWIM:		if (!(sregs->psr & PSR_S)) {		    sregs->trap = TRAP_PRIVI;		    break;		}		*rdd = sregs->wim;		break;	    case RDTBR:		if (!(sregs->psr & PSR_S)) {		    sregs->trap = TRAP_PRIVI;		    break;		}		*rdd = sregs->tbr;		break;	    case WRPSR:		if ((sregs->psr & 0x1f) > 7) {		    sregs->trap = TRAP_UNIMP;		    break;		}		if (!(sregs->psr & PSR_S)) {		    sregs->trap = TRAP_PRIVI;		    break;		}		sregs->psr = (rs1 ^ operand2) & 0x00f03fff;		break;	    case WRWIM:		if (!(sregs->psr & PSR_S)) {		    sregs->trap = TRAP_PRIVI;		    break;		}		sregs->wim = (rs1 ^ operand2) & 0x0ff;		break;	    case WRTBR:		if (!(sregs->psr & PSR_S)) {		    sregs->trap = TRAP_PRIVI;		    break;		}		sregs->tbr = (sregs->tbr & 0x00000ff0) |		    ((rs1 ^ operand2) & 0xfffff000);		break;	    case WRY:                if (!sparclite)                    sregs->y = (rs1 ^ operand2);                else {                    if ( 0 == rd )                        sregs->y = (rs1 ^ operand2);                    else if ( 17 == rd )                        sregs->asr17 = (rs1 ^ operand2);                    else {                        sregs->trap = TRAP_UNIMP;                        break;                    }                }		break;	    case JMPL:#ifdef STAT		sregs->nbranch++;#endif		sregs->icnt = T_JMPL;	/* JMPL takes two cycles */		if (rs1 & 0x3) {		    sregs->trap = TRAP_UNALI;		    break;		}		*rdd = sregs->pc;		npc = rs1 + operand2;		break;	    case RETT:		address = rs1 + operand2;		new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;		sregs->icnt = T_RETT;	/* RETT takes two cycles */		if (sregs->psr & PSR_ET) {		    sregs->trap = TRAP_UNIMP;		    break;		}		if (!(sregs->psr & PSR_S)) {		    sregs->trap = TRAP_PRIVI;		    break;		}		if (sregs->wim & (1 << new_cwp)) {		    sregs->trap = TRAP_WUFL;		    break;		}		if (address & 0x3) {		    sregs->trap = TRAP_UNALI;		    break;		}		sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp | PSR_ET;		sregs->psr =		    (sregs->psr & ~PSR_S) | ((sregs->psr & PSR_PS) << 1);		npc = address;		break;	    case SCAN:		{		  uint32 result, mask;		  int i;		  if (!sparclite) {		     sregs->trap = TRAP_UNIMP;                     break;		  }		  mask = (operand2 & 0x80000000) | (operand2 >> 1);		  result = rs1 ^ mask;		  for (i = 0; i < 32; i++) {		    if (result & 0x80000000)		      break;		    result <<= 1;		  }		  *rdd = i == 32 ? 63 : i;		}		break;	    default:		sregs->trap = TRAP_UNIMP;		break;	    }	}	break;    case 3:			/* Load/store instructions */	address = rs1 + operand2;	if (sregs->psr & PSR_S)	    asi = 11;	 else	    asi = 10;	if (op3 & 4) {	    sregs->icnt = T_ST;	/* Set store instruction count */#ifdef STAT	    sregs->nstore++;#endif	} else {	    sregs->icnt = T_LD;	/* Set load instruction count */#ifdef STAT	    sregs->nload++;#endif	}	/* Decode load/store instructions */	switch (op3) {	case LDDA:	    if (!chk_asi(sregs, &asi, op3)) break;	case LDD:	    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_read(asi, address, ddata, 3, &ws);	    sregs->hold += ws * 2;	    sregs->icnt = T_LDD;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    } else {		rdd[0] = ddata[0];		rdd[1] = ddata[1];#ifdef STAT		sregs->nload++;	/* Double load counts twice */#endif	    }	    break;	case LDA:	    if (!chk_asi(sregs, &asi, op3)) break;	case LD:	    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 {		*rdd = data;	    }	    break;	case LDSTUBA:	    if (!chk_asi(sregs, &asi, op3)) break;	case LDSTUB:	    mexc = memory_read(asi, address, &data, 0, &ws);	    sregs->hold += ws;	    sregs->icnt = T_LDST;	    if (mexc) {		sregs->trap = TRAP_DEXC;		break;	    }	    *rdd = data;	    data = 0x0ff;	    mexc = memory_write(asi, address, &data, 0, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    }#ifdef STAT	    sregs->nload++;#endif	    break;	case LDSBA:	case LDUBA:	    if (!chk_asi(sregs, &asi, op3)) break;	case LDSB:	case LDUB:	    mexc = memory_read(asi, address, &data, 0, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;		break;	    }	    if ((op3 == LDSB) && (data & 0x80))		data |= 0xffffff00;	    *rdd = data;	    break;	case LDSHA:	case LDUHA:	    if (!chk_asi(sregs, &asi, op3)) break;	case LDSH:	case LDUH:	    if (address & 0x1) {		sregs->trap = TRAP_UNALI;		break;	    }	    mexc = memory_read(asi, address, &data, 1, &ws);	    sregs->hold += ws;	    if (mexc) {		sregs->trap = TRAP_DEXC;		break;	    }	    if ((op3 == LDSH) && (data & 0x8000))		data |= 0xffff0000;	    *rdd = data;	    break;	case LDF:	    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->frs1 == rd) ||		    (sregs->frs2 == rd))		    sregs->fhold += (sregs->ftime - ebase.simtime);	    }	    mexc = memory_read(asi, address, &data, 2, &ws);	    sregs->hold += ws;	    sregs->flrd = rd;	    sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +		sregs->hold + sregs->fhold;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    } else {		sregs->fs[rd] = *((float32 *) & data);	    }	    break;	case LDDF:	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;		break;	    }	    if (address & 0x7) {		sregs->trap = TRAP_UNALI;		break;	    }	    if (ebase.simtime < sregs->ftime) {		if (((sregs->frd >> 1) == (rd >> 1)) ||		    ((sregs->frs1 >> 1) == (rd >> 1)) ||		    ((sregs->frs2 >> 1) == (rd >> 1)))		    sregs->fhold += (sregs->ftime - ebase.simtime);	    }	    mexc = memory_read(asi, address, ddata, 3, &ws);	    sregs->hold += ws * 2;	    sregs->icnt = T_LDD;	    if (mexc) {		sregs->trap = TRAP_DEXC;	    } else {		rd &= 0x1E;		sregs->flrd = rd;		sregs->fs[rd] = *((float32 *) & ddata[0]);#ifdef STAT		sregs->nload++;	/* Double load counts twice */#endif		sregs->fs[rd + 1] = *((float32 *) & ddata[1]);		sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +			       sregs->hold + sregs->fhold;	    }	    break;	case LDFSR:	    if (ebase.simtime < sregs->ftime) {		sregs->fhold += (sregs->ftime - ebase.simtime);	    }	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;		break;

⌨️ 快捷键说明

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