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

📄 cpu.c

📁 一个MIPS虚拟机的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (load_byte_from_memory(phyaddr, data))
				return true;
			else 
				return false;
			
		}
}




static boolean  load_halfword_from_memory(UINT32 phyaddr,UINT16 * data)
{
	UINT32 offset;
	//UINT8 halfword_offset;  

	/*notice: last bit of  phyaddr =0,so we must >>1*/
	//halfword_offset = (phyaddr>>1) & 0x00000001;
	//phyaddr = phyaddr & 0xfffffffe;

	if (phyaddr<=RAM_UPPER_BOUND)
		{
			//RAM
			offset = phyaddr - RAM_LOWER_BOUND;
			*data  = bytes2halfword(&ram[offset]);
					
		}
	else if ((phyaddr>=ROM_LOWER_BOUND) && ( phyaddr<=ROM_UPPER_BOUND))
		{
			//ROM
			offset = phyaddr - ROM_LOWER_BOUND;
			*data  = bytes2halfword(&rom[offset]);
					
		}
	else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
		{
			*data = console_load_halfword();
		}
	else
		{
			//bad address exception
			exception(ADEL,-1);
			return false;
		}
}
static boolean load_halfword_from_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT16 * data)
{
	UINT32  index,word_vaddr;
	/*because we just fetch half word form cache. So we must get the offset of cache line.*/
	UINT8 cache_line_offset;  
	
	
	/*notice: last bit of  phyaddr =0,so we must >>1*/
	cache_line_offset = (vaddr>>1) & 0x00000001;
	/*set the last 2 bits to zero*/
	word_vaddr = vaddr & 0xfffffffc;
	
	if (true ==is_swc())
		{
			if (DATA_LOAD == operation_mode  )
				{
					operation_mode = INSTRUCTION_LOAD;
				}
			else if (INSTRUCTION_LOAD == operation_mode  )
				operation_mode = DATA_LOAD;
		}
	
	if (DATA_LOAD==operation_mode)
		{
			index = (phyaddr & DCACHE_MASK) ;
			if ( (is_isc()==true) || (  (dcache[index].tag == word_vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					*data = get_halfword_from_word(dcache[index].cache_line,cache_line_offset);
					return true;
				}
			else
				{
					//miss
				
					return false;
				}
		}
	else if (INSTRUCTION_LOAD==operation_mode)
		{
			index = phyaddr & ICACHE_MASK;
			if ((is_isc()==true)||( (icache[index].tag == word_vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					*data = get_halfword_from_word(icache[index].cache_line,cache_line_offset);
					return true;
				}
			else
				{
					return false;
					
				}
		}
}
static boolean load_halfword(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT16 * data)
{
	if ((phyaddr % 2)!=0)
		{
			//exception
			//bad address
			exception(ADEL,-1);
			return  false;
		}
	
	if (cache_able==true )
		{
			//load a word from cache.
			if (load_halfword_from_cache(vaddr, phyaddr,operation_mode, data))
				return true;
		}
		/*now, cache miss or cache_able=false ,load from ram*/
		{
			//load a word from ram
			if (load_halfword_from_memory(phyaddr, data))
				return true;
			else 
				return false;
			
		}
}

/*Get the instruction of virtual address PC. return instruction. 
true: mean fetch the instruction(no exception occurs)
false: An exception occurs.					*/
static boolean cpu_fetch_instruction(UINT32 * instruction,UINT32 phyaddr,boolean cache_able)
{
	//UINT32 phyaddr;
	//boolean cache_able;
	//fprintf(stderr,"start cpu_fetch_instruction()----------------------------------!\n");
	//fprintf(stderr,"PC=%x,",PC);
	//phyaddr = vaddr2phyaddr(PC,INSTRUCTION_LOAD,&cache_able);
	//fprintf(stderr,"phyaddr=%x,",phyaddr);
	if (0xffffffff==phyaddr)
		{
			// exception
			fprintf(stderr,"Error vaddr->phyaddr,aborting\n ");
			return false;
			
		}
	else
		{
			
			if ( load_word(PC,phyaddr,cache_able,INSTRUCTION_LOAD,instruction))
				{
				//fprintf(stderr,"instruction=%x,",instruction);
				return true;
				}
			else 
				return false;
			
		}
}

/*decode instruciton. jump to different entry.*/
static UINT16 get_op_code (const UINT32 instruction)
{
	
	return ((instruction>>26) & 0x0000003f);
	
	
}
static UINT16 get_rs(const UINT32 instruction)
{
	return (instruction >> 21 ) & 0x0000001f;
}

static UINT16 get_rt(const UINT32 instruction)
{
	return (instruction >> 16 ) & 0x0000001f;
}

static UINT16 get_rd(const UINT32 instruction)
{
	
	return (instruction >> 16 ) & 0x0000001f;
}
static UINT16 get_rd0(const UINT32 instruction)
{
	return (instruction >> 11 ) & 0x0000001f;
}

/*sub operation (bit 5-0)*/
static UINT16 get_sub_opcode(const UINT32 instruction)
{
	return (instruction & 0x0000003f);
}
static UINT16 get_shft(const UINT32 instruction)
{
	return (instruction >> 6 ) & 0x0000001f;
}
static UINT16 get_rw(const UINT32 instruction)
{
	return (instruction >> 16 ) & 0x0000001f;
}

static INT16 get_broffset(const UINT32 instruction)
{
	/*Notice  broffset is a 16 bit signed number.*/
	return instruction & 0x0000ffff;
}
static UINT16  get_const_unsigned(const UINT32 instuction)
{
	return instuction & 0x0000ffff;
}
static INT16  get_const_signed(const UINT32 instuction)
{
	return instuction & 0x0000ffff;
}
static  UINT16 get_rb(const UINT32 instruction)
{
	return (instruction >> 21 ) & 0x0000001f;
}
static INT16 get_offset(const UINT32 instruction)
{
	return instruction & 0x0000ffff;
}
/*all instructions' simualtion---------------------------------  begin(order by opcode)*/
/* opcode=0  sub opcode = 0  sll d,w,shft */
static void sll_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		{
			if ((get_rd0(instruction)==ZERO) && (get_rw(instruction)==ZERO) && (get_shft(instruction)==0))
				printf("nop");
			else	
				printf("%s %s,%s,0x%x","sll",reg_table[get_rd0(instruction)],reg_table[get_rw(instruction)], get_shft(instruction));
		}
		
	cpu_register[get_rd0(instruction)] = cpu_register[get_rw(instruction)] << get_shft(instruction);
}
/* opcode=0  sub opcode = 1 RI exception*/

/* opcode=0  sub opcode = 2 srl d,w,shft*/
static void srl_simulate(const UINT32 instruction)
{
	UINT16 shft;
	shft = get_shft(instruction);
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s,0x%x","srl",reg_table[get_rd0(instruction)],reg_table[get_rw(instruction)], shft);
	if (shft!=0)
		{
			cpu_register[get_rd0(instruction)] = (cpu_register[get_rw(instruction)] >> shft) & ((1<<(32-shft)) -1 );
		}
}
/* opcode=0  sub opcode = 3 */
static void sra_simulate(const UINT32 instruction)
{
	UINT16 shft;
	shft = get_shft(instruction);
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s,0x%x","sra",reg_table[get_rd0(instruction)],reg_table[get_rw(instruction)], shft);
	if (shft!=0)
		{
			if ((cpu_register[get_rw(instruction)] & 0x80000000)==0x80000000)
				{	//the highest bit is 1
					cpu_register[get_rd0(instruction)] = (cpu_register[get_rw(instruction)] >>shft) | (~((1<<(32-shft))-1));
				}
			else
				cpu_register[get_rd0(instruction)] =  (cpu_register[get_rw(instruction)] >>shft) & ((1<<(32-shft))-1) ;
		}
}

/* opcode=0  sub opcode = 4 */
static void sllv_simulate(const UINT32 instruction)
{
	UINT32 rs;
	/* rs=rs%32 */
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s,%s","sllv",reg_table[get_rd0(instruction)],reg_table[get_rt(instruction)], reg_table[get_rs(instruction)]);
	rs = cpu_register[get_rs(instruction)] & 0x0000001f;
	if (rs!=0x00000000)
		cpu_register[get_rd0(instruction)] =  cpu_register[get_rt(instruction)] << (cpu_register[get_rs(instruction)] & 0x0000001f);
}

/* opcode=0  sub opcode = 5   RI*/
/* opcode=0  sub opcode = 6   srlv d,t,s  */
static void srlv_simulate(const UINT32 instruction)
{
	UINT32 rs;
	/* rs=rs%32 */
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s,%s","srlv",reg_table[get_rd0(instruction)],reg_table[get_rt(instruction)], reg_table[get_rs(instruction)]);
	rs = cpu_register[get_rs(instruction)] & 0x0000001f;
	if (rs!=0x00000000)
		cpu_register[get_rd0(instruction)] =  cpu_register[get_rt(instruction)] >> ( (cpu_register[get_rs(instruction)] & 0x0000001f) & ((1<<(32-rs))-1) ) ;
}

/* opcode=0  sub opcode = 7   srav d,t,s  */
static void srav_simulate(const UINT32 instruction)
{
	UINT32 rs;
	/* rs=rs%32 */
	rs = cpu_register[get_rs(instruction)] & 0x0000001f;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s,%s","srav",reg_table[get_rd0(instruction)],reg_table[get_rt(instruction)], reg_table[rs]);
	
	if (rs!=0x00000000)
		{
			if ((cpu_register[get_rt(instruction)] & 0x80000000)==0x80000000)
				{
					cpu_register[get_rd0(instruction)] = (cpu_register[get_rt(instruction)] >>rs) | (~((1<<(32-rs))-1));
				}
			else
				{
					cpu_register[get_rd0(instruction)] =  (cpu_register[get_rt(instruction)] >>rs) & ((1<<(32-rs))-1) ;
				}
		}
}
/* opcode=0  sub opcode = 8   jr s  */
static void jr_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s","jr ", reg_table[get_rs(instruction)]);
	delay_state = DELAYING;
	delay_pc = cpu_register[get_rs(instruction)] ;
	//neednot to save RA register
	//cpu_register[RA] = PC + 8;
}

/* opcode=0  sub opcode = 9  jalr d,s  */
static void jalr_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s","jalr",reg_table[get_rd0(instruction)],reg_table[get_rs(instruction)]);
	
	delay_state = DELAYING;
	delay_pc = cpu_register[get_rs(instruction)] ;
	/* put return address to rd. PC+8(because delay slot)*/
	cpu_register[get_rd0(instruction)] = PC + 8;
}

/* opcode=0  sub opcode = 10,11   RI Exception  */
/* opcode=0  sub opcode = 12   syscall code  */
static void syscall_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s","syscall");
	//system call exception
	exception(SYSCAL,-1);
}

/* opcode=0  sub opcode = 13   break code  */
static void break_simulate(const UINT32 instruction)
{
	//break exception
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s","break");
	exception(BP,-1);
}
/* opcode=0  sub opcode = 14   sdbbp code(MIPS II) ,RI Exception  */
/* opcode=0  sub opcode = 15   sync  ,  not implement  */

/* opcode=0  sub opcode = 16   mfhi d   */
static void mfhi_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s","mfhi",reg_table[get_rd0(instruction)]);
	cpu_register[get_rd0(instruction)] = hi;
}

/* opcode=0  sub opcode = 17   mthi s   */
static void mthi_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s","mthi",reg_table[get_rs(instruction)]);
	hi = cpu_register[get_rs(instruction)] ;
}
/* opcode=0  sub opcode = 18   mflo d   */
static void mflo_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s","mflo",reg_table[get_rd0(instruction)]);
	cpu_register[get_rd0(instruction)] = lo;
}

/* opcode=0  sub opcode = 19   mtflo s   */
static void mtlo_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s","mthlo",reg_table[get_rs(instruction)]);
	lo = cpu_register[get_rs(instruction)] ;
}
/* opcode=0  sub opcode = 20   dsllv d,t,s  MIPS III   */
/* opcode=0  sub opcode =        RI exception             */
/* opcode=0  sub opcode = 22   dsrlv d,t,s  MIPS III   */
/* opcode=0  sub opcode = 23  dsrav d,t,s  MIPS III    */

/* opcode=0  sub opcode = 24  mult s,t   (signed mult)*/
static void mult_simulate(const UINT32 instruction)
{
	INT32 rs,rt;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s","mult",reg_table[get_rs(instruction)],  reg_table[get_rt(instruction)]);
	rs=(INT32)cpu_register[get_rs(instruction)];
	rt=(INT32)cpu_register[get_rt(instruction)];
	mult_signed(&hi,&lo, rs, rt);
	
}
/* opcode=0  sub opcode = 25  multu s,t   (unsigned mult)*/
static void multu_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s","multu",reg_table[get_rs(instruction)],  reg_table[get_rt(instruction)]);
	mult_unsigned(&hi, &lo, cpu_register[get_rs(instruction)], cpu_register[get_rt(instruction)]);
	
}

/* opcode=0  sub opcode = 26  div s,t   (signed div)*/
static void div_simulate(const UINT32 instruction)
{
	INT32 rs,rt;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s","div",reg_table[get_rs(instruction)],  reg_table[get_rt(instruction)]);
	rs =(INT32) cpu_register[get_rs(instruction)];
	rt = (INT32) cpu_register[get_rt(instruction)];
	lo = rs /rt;
	hi = rs%rt;	
}
/* opcode=0  sub opcode = 27  divu s,t   (unsigned div)*/
static void divu_simulate(const UINT32 instruction)
{
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s","divu",reg_table[get_rs(instruction)],  reg_table[get_rt(instruction)]);
	lo =  cpu_register[get_rs(instruction)]/cpu_register[get_rt(instruction)];
	hi =  cpu_register[get_rs(instruction)]%cpu_register[get_rt(instruction)];
}

/* opcode=0  sub opcode = 28  dmult s,t  MIPS III  */
/* opcode=0  sub opcode = 29  dmultu s,t  MIPS III  */
/* opcode=0  sub opcode = 30  ddiv s,t  MIPS III  */
/* opcode=0  sub opcode = 31  ddivu s,t  MIPS III  */
/* opcode=0  sub opcode = 32  add d,s,t  */
static void add_simulate(const UINT32 instruction)
{
	INT32 rs,rt,sum;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,%s,%s","add",reg_table[get_rd0(instruction)] ,reg_table[get_rs(instruction)],  reg_table[get_rt(instruction)]);
	rs=(INT32)cpu_register[get_rs(instruction)];
	rt=(INT32)cpu_register[get_rt(instruction)];
	sum = rs+rt;
	//printf("rs  %x",rs);
	//printf("rt  %x",rt);
	//printf("sum  %x",sum);
	if (((rs<0) && (rt<0) &(sum>=0)) ||((rs>0) && (rt>0) &(sum<=0)))
		{
			//an overflow exception
			exception(OV,-1);
			
		}
	else
		{
			cpu_register[get_rd0(instruction)] = (UINT32) sum;
			//printf(" (UINT32) sum  %x", (UINT32) sum);
		}

	
}

/* opcode=0  sub opcode = 33  addu d,s,t   */
static void addu_simulate(const UINT32 instruction)
{
	//printf("asdfasfd\n");
	//printf("get_rd0(instruction) %d\n",instruction ); 
	//printf("get_rd0(instruction) %d\n",get_rd0(instruction));

⌨️ 快捷键说明

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