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

📄 exec.c

📁 leon2的指令模拟器。leon是应用于航天领域的一款高可靠性的sparc v7指令集的处理器。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * This file is part of SIS. *  * SIS, SPARC instruction simulator V1.8 Copyright (C) 1995 Jiri Gaisler, * European Space Agency *  * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. *  * This program 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 GNU General Public License for * more details. *  * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 675 * Mass Ave, Cambridge, MA 02139, USA. *  */#include "sis.h"#include "end.h"#include <math.h>#include <stdio.h>extern int32    sis_verbose, sparclite;int ext_irl = 0;/* Load/store interlock delay */#define FLSTHOLD 1/* Load delay (delete if unwanted - speeds up simulation) */#define LOAD_DEL 1#define T_LD	2#define T_LDD	3#define T_ST	3#define T_STD	4#define T_LDST	4#define T_JMPL	2#define T_RETT	2#define FSR_QNE 	0x2000#define FP_EXE_MODE 0#define	FP_EXC_PE   1#define FP_EXC_MODE 2#define	FBA	8#define	FBN	0#define	FBNE	1#define	FBLG	2#define	FBUL	3#define	FBL 	4#define	FBUG	5#define	FBG 	6#define	FBU 	7#define FBA	8#define FBE	9#define FBUE	10#define FBGE	11#define FBUGE	12#define FBLE	13#define FBULE	14#define FBO	15#define	FCC_E 	0#define	FCC_L 	1#define	FCC_G 	2#define	FCC_U 	3#define PSR_ET 0x20#define PSR_EF 0x1000#define PSR_PS 0x40#define PSR_S  0x80#define PSR_N  0x0800000#define PSR_Z  0x0400000#define PSR_V  0x0200000#define PSR_C  0x0100000#define PSR_CC 0x0F00000#define PSR_CWP 0x7#define PSR_PIL 0x0f00#define ICC_N	(icc >> 3)#define ICC_Z	(icc >> 2)#define ICC_V	(icc >> 1)#define ICC_C	(icc)#define FP_PRES	(sregs->fpu_pres)#define TRAP_IEXC 1#define TRAP_UNIMP 2#define TRAP_PRIVI 3#define TRAP_FPDIS 4#define TRAP_WOFL 5#define TRAP_WUFL 6#define TRAP_UNALI 7#define TRAP_FPEXC 8#define TRAP_DEXC 9#define TRAP_TAG 10#define TRAP_DIV0 0x2a#define FSR_TT		0x1C000#define FP_IEEE		0x04000#define FP_UNIMP	0x0C000#define FP_SEQ_ERR	0x10000#define	BICC_BN		0#define	BICC_BE		1#define	BICC_BLE	2#define	BICC_BL		3#define	BICC_BLEU	4#define	BICC_BCS	5#define	BICC_NEG	6#define	BICC_BVS	7#define	BICC_BA		8#define	BICC_BNE	9#define	BICC_BG		10#define	BICC_BGE	11#define	BICC_BGU	12#define	BICC_BCC	13#define	BICC_POS	14#define	BICC_BVC	15#define INST_SIMM13 0x1fff#define INST_RS2    0x1f#define INST_I	    0x2000#define ADD 	0x00#define ADDCC 	0x10#define ADDX 	0x08#define ADDXCC 	0x18#define TADDCC 	0x20#define TSUBCC  0x21#define TADDCCTV 0x22#define TSUBCCTV 0x23#define IAND 	0x01#define IANDCC 	0x11#define IANDN 	0x05#define IANDNCC	0x15#define MULScc 	0x24#define DIVScc 	0x1D#define SMUL	0x0B#define SMULCC	0x1B#define UMUL	0x0A#define UMULCC	0x1A#define SDIV	0x0F#define SDIVCC	0x1F#define UDIV	0x0E#define UDIVCC	0x1E#define IOR 	0x02#define IORCC 	0x12#define IORN 	0x06#define IORNCC 	0x16#define SLL 	0x25#define SRA 	0x27#define SRL 	0x26#define SUB 	0x04#define SUBCC 	0x14#define SUBX 	0x0C#define SUBXCC 	0x1C#define IXNOR 	0x07#define IXNORCC	0x17#define IXOR 	0x03#define IXORCC 	0x13#define SETHI 	0x04#define BICC 	0x02#define FPBCC 	0x06#define RDY 	0x28#define RDPSR 	0x29#define RDWIM 	0x2A#define RDTBR 	0x2B#define SCAN 	0x2C#define WRY	0x30#define WRPSR	0x31#define WRWIM	0x32#define WRTBR	0x33#define JMPL 	0x38#define RETT 	0x39#define TICC 	0x3A#define SAVE 	0x3C#define RESTORE 0x3D#define LDD	0x03#define LDDA	0x13#define LD	0x00#define LDA	0x10#define LDF	0x20#define LDDF	0x23#define LDSTUB	0x0D#define LDSTUBA	0x1D#define LDUB	0x01#define LDUBA	0x11#define LDSB	0x09#define LDSBA	0x19#define LDUH	0x02#define LDUHA	0x12#define LDSH	0x0A#define LDSHA	0x1A#define LDFSR	0x21#define ST	0x04#define STA	0x14#define STB	0x05#define STBA	0x15#define STD	0x07#define STDA	0x17#define STF	0x24#define STDFQ	0x26#define STDF	0x27#define STFSR	0x25#define STH	0x06#define STHA	0x16#define SWAP	0x0F#define SWAPA	0x1F#define FLUSH	0x3B#define SIGN_BIT 0x80000000/* # of cycles overhead when a trap is taken */#define TRAP_C  3/* Forward declarations */static uint32	sub_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2,				int32 result));static uint32	add_cc PARAMS ((uint32 psr, int32 operand1, int32 operand2,				int32 result));static void	log_cc PARAMS ((int32 result, struct pstate *sregs));static int	fpexec PARAMS ((uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,				struct pstate *sregs));static int	chk_asi PARAMS ((struct pstate *sregs, uint32 *asi, uint32 op3));extern struct estate ebase;extern int32    nfp,ift;#ifdef ERRINJextern uint32 errtt, errftt;#endifstatic uint32sub_cc(psr, operand1, operand2, result)    uint32          psr;    int32           operand1;    int32           operand2;    int32           result;{    psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));    if (result)	psr &= ~PSR_Z;    else	psr |= PSR_Z;    psr = (psr & ~PSR_V) | ((((operand1 & ~operand2 & ~result) |			   (~operand1 & operand2 & result)) >> 10) & PSR_V);    psr = (psr & ~PSR_C) | ((((~operand1 & operand2) |			 ((~operand1 | operand2) & result)) >> 11) & PSR_C);    return (psr);}uint32add_cc(psr, operand1, operand2, result)    uint32          psr;    int32           operand1;    int32           operand2;    int32           result;{    psr = ((psr & ~PSR_N) | ((result >> 8) & PSR_N));    if (result)	psr &= ~PSR_Z;    else	psr |= PSR_Z;    psr = (psr & ~PSR_V) | ((((operand1 & operand2 & ~result) |			  (~operand1 & ~operand2 & result)) >> 10) & PSR_V);    psr = (psr & ~PSR_C) | ((((operand1 & operand2) |			 ((operand1 | operand2) & ~result)) >> 11) & PSR_C);    return(psr);}static voidlog_cc(result, sregs)    int32           result;    struct pstate  *sregs;{    sregs->psr &= ~(PSR_CC);	/* Zero CC bits */    sregs->psr = (sregs->psr | ((result >> 8) & PSR_N));    if (result == 0)	sregs->psr |= PSR_Z;}/* Add two unsigned 32-bit integers, and calculate the carry out. */static uint32add32 (uint32 n1, uint32 n2, int *carry){  uint32 result = n1 + n2;  *carry = result < n1 || result < n1;  return(result);}/* Multiply two 32-bit integers.  */static voidmul64 (uint32 n1, uint32 n2, uint32 *result_hi, uint32 *result_lo, int msigned){  uint32 lo, mid1, mid2, hi, reg_lo, reg_hi;  int carry;  int sign = 0;  /* If this is a signed multiply, calculate the sign of the result     and make the operands positive.  */  if (msigned)    {      sign = (n1 ^ n2) & SIGN_BIT;      if (n1 & SIGN_BIT)	n1 = -n1;      if (n2 & SIGN_BIT)	n2 = -n2;          }    /* We can split the 32x32 into four 16x16 operations. This ensures     that we do not lose precision on 32bit only hosts: */  lo =   ((n1 & 0xFFFF) * (n2 & 0xFFFF));  mid1 = ((n1 & 0xFFFF) * ((n2 >> 16) & 0xFFFF));  mid2 = (((n1 >> 16) & 0xFFFF) * (n2 & 0xFFFF));  hi =   (((n1 >> 16) & 0xFFFF) * ((n2 >> 16) & 0xFFFF));    /* We now need to add all of these results together, taking care     to propogate the carries from the additions: */  reg_lo = add32 (lo, (mid1 << 16), &carry);  reg_hi = carry;  reg_lo = add32 (reg_lo, (mid2 << 16), &carry);  reg_hi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);  /* Negate result if necessary. */  if (sign)    {      reg_hi = ~ reg_hi;      reg_lo = - reg_lo;      if (reg_lo == 0)	reg_hi++;    }    *result_lo = reg_lo;  *result_hi = reg_hi;}/* Divide a 64-bit integer by a 32-bit integer.  We cheat and assume   that the host compiler supports long long operations.  */static voiddiv64 (uint32 n1_hi, uint32 n1_low, uint32 n2, uint32 *result, int msigned){  uint64 n1;  n1 = ((uint64) n1_hi) << 32;  n1 |= ((uint64) n1_low) & 0xffffffff;  if (msigned)    {      int64 n1_s = (int64) n1;      int32 n2_s = (int32) n2;      n1_s = n1_s / n2_s;      n1 = (uint64) n1_s;    }  else    n1 = n1 / n2;  *result = (uint32) (n1 & 0xffffffff);}intdispatch_instruction(sregs)    struct pstate  *sregs;{    uint32          cwp, op, op2, op3, asi, rd, cond, rs1,                    rs2;    uint32          ldep, icc;    int32           operand1, operand2, *rdd, result, eicc,                    new_cwp;    int32           pc, npc, data, address, ws, mexc, fcc;    int32	    ddata[2];    sregs->ninst++;    cwp = ((sregs->psr & PSR_CWP) << 4);    op = sregs->inst >> 30;    pc = sregs->npc;    npc = sregs->npc + 4;    op3 = rd = rs1 = operand2 = eicc = 0;    rdd = 0;    if (op & 2) {	op3 = (sregs->inst >> 19) & 0x3f;	rs1 = (sregs->inst >> 14) & 0x1f;	rd = (sregs->inst >> 25) & 0x1f;#ifdef LOAD_DEL	/* Check if load dependecy is possible */	if (ebase.simtime <= sregs->ildtime)	    ldep = (((op3 & 0x38) != 0x28) && ((op3 & 0x3e) != 0x34) && (sregs->ildreg != 0));        else	    ldep = 0;	if (sregs->inst & INST_I) {	    if (ldep && (sregs->ildreg == rs1))		sregs->hold++;	    operand2 = sregs->inst;	    operand2 = ((operand2 << 19) >> 19);	/* sign extend */	} else {	    rs2 = sregs->inst & INST_RS2;	    if (rs2 > 7)		operand2 = sregs->r[(cwp + rs2) & 0x7f];	    else		operand2 = sregs->g[rs2];	    if (ldep && ((sregs->ildreg == rs1) || (sregs->ildreg == rs2)))		sregs->hold++;	}#else	if (sregs->inst & INST_I) {	    operand2 = sregs->inst;	    operand2 = ((operand2 << 19) >> 19);	/* sign extend */	} else {	    rs2 = sregs->inst & INST_RS2;	    if (rs2 > 7)		operand2 = sregs->r[(cwp + rs2) & 0x7f];	    else		operand2 = sregs->g[rs2];	}#endif	if (rd > 7)	    rdd = &(sregs->r[(cwp + rd) & 0x7f]);	else	    rdd = &(sregs->g[rd]);	if (rs1 > 7)	    rs1 = sregs->r[(cwp + rs1) & 0x7f];	else	    rs1 = sregs->g[rs1];    }    switch (op) {    case 0:	op2 = (sregs->inst >> 22) & 0x7;	switch (op2) {	case SETHI:	    rd = (sregs->inst >> 25) & 0x1f;	    if (rd > 7)		rdd = &(sregs->r[(cwp + rd) & 0x7f]);	    else		rdd = &(sregs->g[rd]);	    *rdd = sregs->inst << 10;	    break;	case BICC:#ifdef STAT	    sregs->nbranch++;#endif	    icc = sregs->psr >> 20;	    cond = ((sregs->inst >> 25) & 0x0f);	    switch (cond) {	    case BICC_BN:		eicc = 0;		break;	    case BICC_BE:		eicc = ICC_Z;		break;	    case BICC_BLE:		eicc = ICC_Z | (ICC_N ^ ICC_V);		break;	    case BICC_BL:		eicc = (ICC_N ^ ICC_V);		break;	    case BICC_BLEU:		eicc = ICC_C | ICC_Z;		break;	    case BICC_BCS:		eicc = ICC_C;		break;	    case BICC_NEG:		eicc = ICC_N;		break;	    case BICC_BVS:		eicc = ICC_V;		break;	    case BICC_BA:		eicc = 1;		if (sregs->inst & 0x20000000)		    sregs->annul = 1;		break;	    case BICC_BNE:		eicc = ~(ICC_Z);		break;	    case BICC_BG:		eicc = ~(ICC_Z | (ICC_N ^ ICC_V));		break;	    case BICC_BGE:		eicc = ~(ICC_N ^ ICC_V);		break;	    case BICC_BGU:		eicc = ~(ICC_C | ICC_Z);		break;	    case BICC_BCC:		eicc = ~(ICC_C);		break;	    case BICC_POS:		eicc = ~(ICC_N);		break;	    case BICC_BVC:		eicc = ~(ICC_V);		break;	    }	    if (eicc & 1) {		operand1 = sregs->inst;		operand1 = ((operand1 << 10) >> 8);	/* sign extend */		npc = sregs->pc + operand1;	    } else {		if (sregs->inst & 0x20000000)		    sregs->annul = 1;	    }	    break;	case FPBCC:#ifdef STAT	    sregs->nbranch++;#endif	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;		break;	    }	    if (ebase.simtime < sregs->ftime) {		sregs->ftime = ebase.simtime + sregs->hold;	    }	    cond = ((sregs->inst >> 25) & 0x0f);	    fcc = (sregs->fsr >> 10) & 0x3;	    switch (cond) {	    case FBN:		eicc = 0;		break;	    case FBNE:		eicc = (fcc != FCC_E);		break;	    case FBLG:		eicc = (fcc == FCC_L) || (fcc == FCC_G);		break;	    case FBUL:		eicc = (fcc == FCC_L) || (fcc == FCC_U);		break;	    case FBL:		eicc = (fcc == FCC_L);		break;	    case FBUG:		eicc = (fcc == FCC_G) || (fcc == FCC_U);		break;	    case FBG:		eicc = (fcc == FCC_G);		break;	    case FBU:		eicc = (fcc == FCC_U);		break;	    case FBA:		eicc = 1;		if (sregs->inst & 0x20000000)		    sregs->annul = 1;		break;	    case FBE:		eicc = !(fcc != FCC_E);		break;	    case FBUE:		eicc = !((fcc == FCC_L) || (fcc == FCC_G));		break;	    case FBGE:		eicc = !((fcc == FCC_L) || (fcc == FCC_U));		break;	    case FBUGE:		eicc = !(fcc == FCC_L);		break;	    case FBLE:		eicc = !((fcc == FCC_G) || (fcc == FCC_U));		break;	    case FBULE:		eicc = !(fcc == FCC_G);		break;	    case FBO:		eicc = !(fcc == FCC_U);		break;	    }	    if (eicc) {		operand1 = sregs->inst;		operand1 = ((operand1 << 10) >> 8);	/* sign extend */		npc = sregs->pc + operand1;	    } else {		if (sregs->inst & 0x20000000)		    sregs->annul = 1;	    }	    break;	default:	    sregs->trap = TRAP_UNIMP;	    break;	}	break;    case 1:			/* CALL */#ifdef STAT	sregs->nbranch++;#endif	sregs->r[(cwp + 15) & 0x7f] = sregs->pc;	npc = sregs->pc + (sregs->inst << 2);	break;    case 2:	if ((op3 >> 1) == 0x1a) {	    if (!((sregs->psr & PSR_EF) && FP_PRES)) {		sregs->trap = TRAP_FPDIS;	    } else {		rs1 = (sregs->inst >> 14) & 0x1f;		rs2 = sregs->inst & 0x1f;		sregs->trap = fpexec(op3, rd, rs1, rs2, sregs);	    }	} else {	    switch (op3) {	    case TICC:	        icc = sregs->psr >> 20;	        cond = ((sregs->inst >> 25) & 0x0f);	        switch (cond) {		case BICC_BN:		    eicc = 0;		    break;		case BICC_BE:		    eicc = ICC_Z;		    break;		case BICC_BLE:		    eicc = ICC_Z | (ICC_N ^ ICC_V);		    break;		case BICC_BL:		    eicc = (ICC_N ^ ICC_V);		    break;		case BICC_BLEU:		    eicc = ICC_C | ICC_Z;		    break;		case BICC_BCS:		    eicc = ICC_C;		    break;		case BICC_NEG:		    eicc = ICC_N;		    break;		case BICC_BVS:		    eicc = ICC_V;		    break;	        case BICC_BA:		    eicc = 1;		    break;	        case BICC_BNE:		    eicc = ~(ICC_Z);		    break;	        case BICC_BG:		    eicc = ~(ICC_Z | (ICC_N ^ ICC_V));		    break;	        case BICC_BGE:		    eicc = ~(ICC_N ^ ICC_V);		    break;	        case BICC_BGU:		    eicc = ~(ICC_C | ICC_Z);		    break;	        case BICC_BCC:		    eicc = ~(ICC_C);		    break;	        case BICC_POS:		    eicc = ~(ICC_N);		    break;	        case BICC_BVC:		    eicc = ~(ICC_V);		    break;		}		if (eicc & 1) {		    sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));		}		break;	    case MULScc:		operand1 =		    (((sregs->psr & PSR_V) ^ ((sregs->psr & PSR_N) >> 2))

⌨️ 快捷键说明

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