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

📄 cpu.c

📁 一个MIPS虚拟机的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (!load_halfword(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
			{
				//an exception has occured when load_halfword
					
			}
		else
			{
				/*we must convert data to signed value*/
				return_value = (INT16)data;
				cpu_register[get_rt(instruction)]= (INT32)return_value;
			}
	//}
	
	
}
/* lwl algorithms is taken from VMIPS*/
UINT32 
lwl(UINT32 regval, UINT32 memval, UINT8 offset)
{
	if (target_end==BIGEND) {
		switch (offset)
		{
			case 0: return memval;
			case 1: return ((memval & 0xffffff) << 8) | (regval & 0xff);
			case 2: return ((memval & 0xffff) << 16) | (regval & 0xffff);
			case 3: return ((memval & 0xff) << 24) | (regval & 0xffffff);
		}
	} else /* if MIPS target is little endian */ {
		switch (offset)
		{
			case 0: return ((memval & 0xff)) << 24 | (regval & 0xffffff);
			case 1: return ((memval & 0xffff)) << 16 | (regval & 0xffff);
			case 2: return ((memval & 0xffffff)) << 8 | (regval & 0xff);
			case 3: return memval;
		}
	}
	//fprintf("""Invalid offset %x passed to lwl\n", offset);
}
UINT32
lwr(UINT32 regval, UINT32 memval, UINT8 offset)
{
	if (target_end==BIGEND) {
		switch (offset)
		{
			case 0: return (regval & 0xffffff00) |
						((unsigned)(memval & 0xff000000) >> 24);
			case 1: return (regval & 0xffff0000) |
						((unsigned)(memval & 0xffff0000) >> 16);
			case 2: return (regval & 0xff000000) |
						((unsigned)(memval & 0xffffff00) >> 8);
			case 3: return memval;
		}
	} else /* if MIPS target is little endian */ {
		switch (offset)
		{
			/* The SPIM source claims that "The description of the
			 * little-endian case in Kane is totally wrong." The fact
			 * that I ripped off the LWR algorithm from them could be
			 * viewed as a sort of passive assumption that their claim
			 * is correct.
			 */
			case 0: /* 3 in book */
				return memval;
			case 1: /* 0 in book */
				return (regval & 0xff000000) | ((memval & 0xffffff00) >> 8);
			case 2: /* 1 in book */
				return (regval & 0xffff0000) | ((memval & 0xffff0000) >> 16);
			case 3: /* 2 in book */
				return (regval & 0xffffff00) | ((memval & 0xff000000) >> 24);
		}
	}
	//fatal_error("Invalid offset %x passed to lwr\n", offset);
}


/*opcode = 34  lwl t,0(b)*/
static void lwl_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr,wordvaddr;
	INT32 offset;
	boolean cache_able;
	UINT8 word_offset;
	UINT32 memory_data;

	offset = get_offset(instruction);
	base_addr = cpu_register[get_rb(instruction)];
	vaddr = base_addr +  offset;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,0x%x(%s)","lwl",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
	/**/
	wordvaddr = vaddr & 0xfffffffc;
	word_offset = vaddr & 0x00000003;
	if ((vaddr % 4)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	
	phyaddr = vaddr2phyaddr(wordvaddr,DATA_LOAD,&cache_able);
	if ((phyaddr % 4)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	if (0xffffffff== phyaddr  )
		{
			//an exception has occured 
		}
	else
		{
			if (!load_word(vaddr,phyaddr,cache_able,DATA_LOAD,&memory_data))
				{	//an exception has occured
				}
			else
				{
					cpu_register[get_rt(instruction)] = lwl(cpu_register[get_rt(instruction)], memory_data, word_offset);
				}
		}
	
}


/*opcode = 35  lw t,0(b)*/
static void lw_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr;
	INT32 offset;
	boolean cache_able;
	UINT32 data;
	INT32 return_value;
	
	offset = get_offset(instruction);
	base_addr = cpu_register[get_rb(instruction)];
	vaddr = base_addr +  offset;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,0x%x(%s)","lw",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
	//printf("base_addr 0x%x\n",base_addr);
	//printf("base_addr 0x%x\n",offset);
	//printf("vaddr 0x%x\n",vaddr);
	if ((vaddr % 4)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	phyaddr = vaddr2phyaddr(vaddr,DATA_LOAD,&cache_able);
	if ((phyaddr % 4)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	//printf("phyaddr 0x%x",phyaddr);
	if (0xffffffff ==phyaddr  )
		{
			//an exception has occured when addr->phyaddr
		}
	else
		{
			if (!load_word(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
				{
					//printf("exception \n");
					//an exception has occured when load_halfword
					
				}
			else
				{
					/*we must convert data to signed value*/
					//printf("data 0x%x\n",data);
					return_value = (INT32)data;
					cpu_register[get_rt(instruction)]= (INT32)return_value;
				}
		}
	
}

/*opcode = 36  lbu t,0(b)*/
static void lbu_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr;
	INT32 offset;
	boolean cache_able;
	UINT8 data;
	UINT8 return_value;
	
	offset = get_offset(instruction);
	base_addr = cpu_register[get_rb(instruction)];
	vaddr = base_addr +  offset;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,0x%x(%s)","lbu",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
	phyaddr = vaddr2phyaddr(vaddr,DATA_LOAD,&cache_able);
	if (0xffffffff== phyaddr  )
		{
			//an exception has occured when addr->phyaddr
		}
	else
		{
			if (!load_byte(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
				{
					//an exception has occured when load_halfword
					
				}
			else
				{
					/*we must convert data to signed value*/
					return_value = (UINT8)data;
					cpu_register[get_rt(instruction)]= (UINT32)return_value;
				}
		}
	
}


/*opcode = 37  lhu t,0(b)*/
static void lhu_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr;
	INT32 offset;
	boolean cache_able;
	UINT16 data;
	UINT16 return_value;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,0x%x(%s)","lhu",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
	offset = get_offset(instruction);
	base_addr = cpu_register[get_rb(instruction)];
	vaddr = base_addr +  offset;
	if ((vaddr % 2)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	phyaddr = vaddr2phyaddr(vaddr,DATA_LOAD,&cache_able);
	if ((vaddr % 2)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	if (0xffffffff== phyaddr  )
		{
			//an exception has occured when addr->phyaddr
		}
	else
		{
			if (!load_halfword(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
				{
					//an exception has occured when load_halfword
					
				}
			else
				{
					/*we must convert data to signed value*/
					return_value = (UINT16)data;
					cpu_register[get_rt(instruction)]= (UINT32)return_value;
				}
		}
	
}

/*opcode = 38  lwr  t,0(b)*/
static void lwr_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr,wordvaddr;
	INT32 offset;
	boolean cache_able;
	UINT8 word_offset;
	UINT32 memory_data;

	offset = get_offset(instruction);
	base_addr = cpu_register[get_rb(instruction)];
	vaddr = base_addr +  offset;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,0x%x(%s)","lwr",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
	/**/
	wordvaddr = vaddr & 0xfffffffc;
	word_offset = vaddr & 0x00000003;
	if ((vaddr % 4)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	phyaddr = vaddr2phyaddr(wordvaddr,DATA_LOAD,&cache_able);
	if ((phyaddr % 4)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
				exception(ADEL,-1);
			//else
			//	exception(ADES,-1);
			return ;
		}
	if (0xffffffff== phyaddr  )
		{
			//an exception has occured 
		}
	else
		{
			if (!load_word(vaddr,phyaddr,cache_able,DATA_LOAD,&memory_data))
				{	//an exception has occured
				}
			else
				{
					cpu_register[get_rt(instruction)] = lwr(cpu_register[get_rt(instruction)], memory_data, word_offset);
				}
		}
	
}


/*opcode = 39  lwu  t,0(b) MIPS III*/

/*opcode = 40   sb  t,0(b)*/
static void sb_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr;
	INT32 offset;
	boolean cache_able;
	UINT8 data;
	

	offset = get_offset(instruction);
	base_addr = cpu_register[get_rb(instruction)];
	vaddr = base_addr +  offset;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,0x%x(%s)","sb",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
	data = cpu_register[get_rt(instruction)]&0x000000ff;
	phyaddr = vaddr2phyaddr(vaddr,DATA_STORE,&cache_able);
	if (0xffffffff== phyaddr  )
		{
			//an exception has occured
		}
	else
		{
			store_byte(vaddr,phyaddr,cache_able,DATA_STORE,data);
				
		}
	
	
}

/*opcode = 41   sh  t,0(b)*/
static void sh_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr;
	INT32 offset;
	boolean cache_able;
	UINT16 data;
	

	offset = get_offset(instruction);
	base_addr = cpu_register[get_rb(instruction)];
	vaddr = base_addr +  offset;
	if ((options.debug_mode==true) && (debug.current_mode==STEP))
		printf("%s %s,0x%x(%s)","sh",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
	data = cpu_register[get_rt(instruction)]&0x0000ffff;
	if ((vaddr % 2)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
			//	exception(ADEL,-1);
			//else
				exception(ADES,-1);
			return ;
		}
	phyaddr = vaddr2phyaddr(vaddr,DATA_STORE,&cache_able);
	if ((phyaddr % 2)!=0)
		{
			//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
			//bad address exctiption
			//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
			//	exception(ADEL,-1);
			//else
				exception(ADES,-1);
			return ;
		}
	if (0xffffffff== phyaddr  )
		{
			//an exception has occured
		}
	else
		{
			store_halfword(vaddr,phyaddr,cache_able,DATA_STORE,data);
				
		}
	
	
}

UINT32
swl(UINT32 regval, UINT32 memval, UINT8 offset)
{
	if (host_end) {
		switch (offset) {
			case 0: return regval; 
			case 1: return (memval & 0xff000000) | (regval >> 8 & 0xffffff); 
			case 2: return (memval & 0xffff0000) | (regval >> 16 & 0xffff); 
			case 3: return (memval & 0xffffff00) | (regval >> 24 & 0xff); 
		}
	} else /* if MIPS target is little endian */ {
		switch (offset) {
			case 0: return (memval & 0xffffff00) | (regval >> 24 & 0xff); 
			case 1: return (memval & 0xffff0000) | (regval >> 16 & 0xffff); 
			case 2: return (memval & 0xff000000) | (regval >> 8 & 0xffffff); 
			case 3: return regval; 
		}
	}
	//fatal_error("Invalid offset %x passed to swl\n", offset);
}

UINT32
swr(UINT32 regval, UINT32 memval, UINT8 offset)
{
	if (host_end) {
		switch (offset) {
			case 0: return ((regval << 24) & 0xff000000) | (memval & 0xffffff); 
			case 1: return ((regval << 16) & 0xffff0000) | (memval & 0xffff); 
			case 2: return ((regval << 8) & 0xffffff00) | (memval & 0xff); 
			case 3: return regval; 
		}
	} else /* if MIPS target is little endian */ {
		switch (offset) {
			case 0: return regval; 
			case 1: return ((regval << 8) & 0xffffff00) | (memval & 0xff); 
			case 2: return ((regval << 16) & 0xffff0000) | (memval & 0xffff); 
			case 3: return ((regval << 24) & 0xff000000) | (memval & 0xffffff); 
		}
	}
	//fatal_error("Invalid offset %x passed to swr\n", offset);
}

/*opcode = 42   swl t,0(b)*/
static void swl_simulate(const UINT32 instruction)
{
	UINT32 base_addr,vaddr,phyaddr;
	INT32 offset;

⌨️ 快捷键说明

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