?? cpu.c
字號:
#ifdef EXTERN
#undef EXTERN
#endif
#define EXTERN extern
#include "global.h"
static char reg_table[CPU_REGISTER_NUMBER][5]=
{
"zero","at","v0","v1","a0",
"a1","a2","a3","t0","t1",
"t2","t3","t4","t5","t6",
"t7","s0","s1","s2","s3",
"s4","s5","s6","s7","t8",
"t9","k0","k1","gp","sp",
"s8","ra"
};
static void cpu_reset()
{
PC = ROM_RESET_BASE_ADDR;
}
static void disable_cacheline(UINT32 vaddr,UINT32 phyaddr,int operation_mode)
{
UINT32 index,word_vaddr;
word_vaddr = vaddr & 0xfffffffc;
if (is_swc()==true)
{
if (operation_mode == DATA_STORE)
{
operation_mode = INSTRUCTION_STORE;
}
else if (operation_mode == INSTRUCTION_STORE)
operation_mode = DATA_STORE;
}
if (operation_mode==DATA_STORE)
{
index = (phyaddr & DCACHE_MASK) ;
if ( (is_isc()==true) || ( (dcache[index].tag == word_vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
{
//hit
dcache[index].flag = ~CACHE_VALID_MASK;
}
}
else if (operation_mode==INSTRUCTION_STORE)
{
index = phyaddr & ICACHE_MASK;
if ((is_isc()==true)||( (icache[index].tag == word_vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
{
//hit
icache[index].flag = ~CACHE_VALID_MASK;
}
}
}
/*if exception has occured, return false,else return true*/
static boolean store_halfword_into_memory(UINT32 phyaddr,UINT16 data)
{
UINT32 offset;
if (phyaddr<=RAM_UPPER_BOUND)
{
//RAM
offset = phyaddr - RAM_LOWER_BOUND;
//ram[offset] = data;
halfword2bytes(data, &ram[offset] );
return true;
}
else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
{
console_store_byte(phyaddr,data);
}
else
{
//bad address exception
exception(ADES,-1);
return false;
}
}
static boolean store_halfword(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT16 data)
{
if ((phyaddr % 2)!=0)
{
//exception
//bad address
exception(ADES,-1);
return false;
}
// now we store a word into memory
// and disable cache
if (store_halfword_into_memory(phyaddr,data))
{
disable_cacheline(vaddr,phyaddr,operation_mode);
return true;
}
else
return false;
}
static boolean store_word_into_memory(UINT32 phyaddr,UINT32 data)
{
UINT32 offset;
//printf("phyaddr %x",phyaddr);
if (phyaddr<=RAM_UPPER_BOUND)
{
//RAM
offset = phyaddr - RAM_LOWER_BOUND;
word2bytes(data, &ram[offset] );
return true;
}
else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
{
console_store_byte(phyaddr,data);
}
else
{
//bad address exception
exception(ADES,-1);
return false;
}
}
static boolean store_word(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT32 data)
{
if ((phyaddr % 4)!=0)
{
//exception
//bad address
exception(ADES,-1);
return false;
}
// now we store a word into memory
// and disable cache
if (store_word_into_memory(phyaddr,data))
{
disable_cacheline(vaddr,phyaddr,operation_mode);
return true;
}
else
return false;
}
static boolean store_byte_into_memory(UINT32 phyaddr,UINT8 data)
{
UINT32 offset;
if (phyaddr<=RAM_UPPER_BOUND)
{
//RAM
offset = phyaddr - RAM_LOWER_BOUND;
ram[offset] = data;
return true;
}
else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
{
console_store_byte(phyaddr,data);
}
else
{
//bad address exception
exception(ADES,-1);
return false;
}
}
static boolean store_byte(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT8 data)
{
// now we store a byte into memory
// and disable cache
UINT32 word_vaddr;
if (store_byte_into_memory(phyaddr,data))
{
disable_cacheline(vaddr,phyaddr,operation_mode);
return true;
}
else
return false;
}
/* load a word from memory. Memory includes RAM and ROM.
If exception occurs,return false, else return true*/
static boolean load_word_from_memory(UINT32 phyaddr,UINT32 * data)
{
UINT32 offset;
//fprintf(stderr,"start load_word_from_memory\n");
if (phyaddr<=RAM_UPPER_BOUND)
{
//RAM
//fprintf(stderr,"RAM\n");
offset = phyaddr - RAM_LOWER_BOUND;
*data = bytes2word(&ram[offset]);
return true;
}
else if ((phyaddr>=ROM_LOWER_BOUND) && ( phyaddr<=ROM_UPPER_BOUND))
{
//ROM
//fprintf(stderr,"ROM\n");
offset = phyaddr - ROM_LOWER_BOUND;
//fprintf(stderr,"offset= %d\n",offset);
*data = bytes2word(&rom[offset]);
//fprintf(stderr,"*data = %x\n",*data );
return true;
}
else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
{
*data = console_load_word(phyaddr);
}
else
{
//bad address exception
exception(ADEL,-1);
return false;
}
}
/* if hit ,return true, else return false*/
static boolean load_word_from_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT32 * data)
{
UINT32 index;
if (true==is_swc())
{
if (DATA_LOAD ==operation_mode )
{
operation_mode = INSTRUCTION_LOAD;
}
else if (operation_mode == INSTRUCTION_LOAD)
operation_mode = DATA_LOAD;
}
if (DATA_LOAD == operation_mode)
{
index = (phyaddr & DCACHE_MASK) ;
if ( (true ==is_isc()) || ( (dcache[index].tag == vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
{
//hit
*data = dcache[index].cache_line;
return true;
}
else
{
//miss
return false;
}
}
else if (INSTRUCTION_LOAD==operation_mode)
{
index = phyaddr & ICACHE_MASK;
if ((true ==is_isc())||( (icache[index].tag == vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
{
//hit
*data = icache[index].cache_line;
return true;
}
else
{
return false;
}
}
}
/*When we load a word, if cache miss ,then we must load the word form ram and set to cache*/
static void set_word_to_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT32 data)
{
UINT32 index;
if (true ==is_isc())
{
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) ;
dcache[index].cache_line = data;
dcache[index].tag = vaddr;
dcache[index].flag =CACHE_VALID_MASK;
}
else if (INSTRUCTION_LOAD ==operation_mode)
{
index = (phyaddr & ICACHE_MASK) ;
icache[index].cache_line = data;
icache[index].tag = vaddr;
icache[index].flag =ICACHE_MASK;
}
}
/*load a word from phyaddr..*/
static boolean load_word(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT32 * data)
{
if ((phyaddr % 4)!=0)
{
//exception
//bad address
exception(ADEL,-1);
return false;
}
if (true == cache_able)
{
//load a word from cache.
if (load_word_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_word_from_memory(phyaddr, data))
{
//printf("*data %x \n",*data);
// set the word to cache.
// Now we only set the cache line if and only if we load a word.
// That means when loading a hb or byte, we do not set the cache line.
if (cache_able==true )
set_word_to_cache(vaddr,phyaddr,operation_mode,*data);
return true;
}
}
static boolean load_byte_from_memory(UINT32 phyaddr,UINT8 * data)
{
UINT32 offset;
//UINT8 byte_offset;
//byte_offset = phyaddr & 0x00000003;
//phyaddr = phyaddr & 0xfffffffc;
if (phyaddr<=RAM_UPPER_BOUND)
{
//RAM
offset = phyaddr - RAM_LOWER_BOUND;
*data = ram[offset];
}
else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
{
*data =console_load_byte();
}
else if ((phyaddr>=ROM_LOWER_BOUND) && ( phyaddr<=ROM_UPPER_BOUND))
{
//ROM
offset = phyaddr - ROM_LOWER_BOUND;
*data = rom[offset];
}
else
{
//bad address exception
exception(ADEL,-1);
return false;
}
}
static boolean load_byte_from_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT8 * data)
{
UINT32 index,word_vaddr;
/*because we just fetch byte form cache. So we must get the offset of cache line.*/
UINT8 cache_line_offset;
cache_line_offset = vaddr & 0x00000003;
/*set the last 2 bits to zero*/
word_vaddr = vaddr & 0xfffffffc;
//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 ( (true==is_isc()) || ( (dcache[index].tag == word_vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
{
//hit
*data = get_byte_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 ((true==is_isc())||( (icache[index].tag == word_vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
{
//hit
*data = get_byte_from_word(icache[index].cache_line,cache_line_offset);
return true;
}
else
{
return false;
}
}
}
static boolean load_byte(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT8 * data)
{
if (true == cache_able )
{
//load a byte from cache.
if (load_byte_from_cache(vaddr, phyaddr,operation_mode, data))
return true;
}
/*now, cache miss or cache_able=false ,load from ram*/
{
//load a byte from ram
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -