Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update by Jan.29th, 2021
Add support to trap instructions
Add support to conditional branch (and link) instructions.
Add support to clo/clz instructions.
Add support to unaligned memory access instructions (lwl/lwr/swl/swr).
By now, I assume there is only coprocessor instructions remaining unsupported by mipsivm in comparison to MARS.
Add test case for unaligned memory accesses.
Fix disassembly in nop instruction.
Fix missing disassembly compilation in free script preset.
Update readme.
  • Loading branch information
yat17006 committed Jan 28, 2021
1 parent 28c9d8e commit 2f34872
Show file tree
Hide file tree
Showing 16 changed files with 1,065 additions and 336 deletions.
3 changes: 2 additions & 1 deletion .gitattributes
Expand Up @@ -2,4 +2,5 @@
* text=auto
*.c linguist-language=C
*.h linguist-language=C
*.asm linguist-language=Assembly
*.asm linguist-language=Assembly
*.s linguist-language=Assembly
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -71,6 +71,7 @@ Each PTE is an 8-byte entry. There are 512 PTEs. For each entry, there are 64 bi
| PDE | Page-Directory Entry | The second level of address-translation |
| PDPTE | Page-Directory Pointer Table Entry | The third level of address-translation |
| XTLB | Execution Translate Lookaside Buffer | TLB that accelerates instruction fetching |
| DTLB | Data Translate Lookaside Buffer | TLB that accelerates data reading/writing |

## FAQ
Following lists the frequently asked questions, and corresponding answers.
Expand Down Expand Up @@ -103,6 +104,7 @@ Here list all command-line arguments.

- `/nologo` suppresses the logo printer.
- `/runtime` specifies the runtime preset of MIPS Virtual Machine. Default runtime preset is `MARS`.
- `/debug` specifies mipsivm to break at program startup.

Following runtime presets are available:

Expand All @@ -121,5 +123,15 @@ mipsivm /nologo /runtime mars /ds helloworld.data.bin /ts helloworld.text.bin
```
This code would suppress the logo printer then load `helloworld.data.bin` as `.data` section and `helloworld.text.bin` as `.text` section of the program, with 64KiB default stack, and run the program.

## Debug Mode
Debugging is the new feature of mipsivm. In case of break-on-startup, `break` instructions or `trap` instructions, mipsivm would enter debug mode and accepts command line input to debug. <br>
Following are debug commands:
- `d` is dumping command: Dump memory content and display in console. (Not started)
- `e` is editing command: Edit memory content. (Not started)
- `g` is continue command: Continue simulation of program.
- `r` is register dump command: Dump register file and display in console.
- `t` is single-step command: Start single-stepping with instruction-granularity.
- `u` is disassembly command: Disassemble instructions display in console. (Incomplete)

## License
This repository is licensed under the MIT license.
6 changes: 6 additions & 0 deletions compfre_win10x64.bat
Expand Up @@ -27,6 +27,12 @@ cl .\src\sim-i.c /I".\src\include" /Zi /nologo /W3 /WX /Oi /O2 /D"_msvc" /D"_amd

cl .\src\sim-j.c /I".\src\include" /Zi /nologo /W3 /WX /Oi /O2 /D"_msvc" /D"_amd64" /D"_mips_simj" /Zc:wchar_t /Zc:forScope /FAcs /Fa"%objpath%\sim-j.cod" /Fo"%objpath%\sim-j.obj" /Fd"%objpath%\vc140.pdb" /Qspectre /GS- /Gd /TC /c /errorReport:queue

cl .\src\disasm-r.c /I".\src\include" /Zi /nologo /W3 /WX /Oi /O2 /D"_msvc" /D"_amd64" /D"_mips_disasmr" /Zc:wchar_t /Zc:forScope /FAcs /Fa"%objpath%\disasm-r.cod" /Fo"%objpath%\disasm-r.obj" /Fd"%objpath%\vc140.pdb" /Qspectre /GS- /Gd /TC /c /errorReport:queue

cl .\src\disasm-i.c /I".\src\include" /Zi /nologo /W3 /WX /Oi /O2 /D"_msvc" /D"_amd64" /D"_mips_disasmi" /Zc:wchar_t /Zc:forScope /FAcs /Fa"%objpath%\disasm-i.cod" /Fo"%objpath%\disasm-i.obj" /Fd"%objpath%\vc140.pdb" /Qspectre /GS- /Gd /TC /c /errorReport:queue

cl .\src\disasm.c /I".\src\include" /Zi /nologo /W3 /WX /Oi /O2 /D"_msvc" /D"_amd64" /D"_mips_disasm" /Zc:wchar_t /Zc:forScope /FAcs /Fa"%objpath%\disasm.cod" /Fo"%objpath%\disasm.obj" /Fd"%objpath%\vc140.pdb" /Qspectre /GS- /Gd /TC /c /errorReport:queue

echo ============Start Linking============
link "%objpath%\*.obj" /LIBPATH:"%libpath%\um\x64" /LIBPATH:"%libpath%\ucrt\x64" /LIBPATH:"%ddkpath%\lib\x64" /NOLOGO /DEBUG /PDB:"%objpath%\mipsivm.pdb" /INCREMENTAL:NO /OUT:"%binpath%\mipsivm.exe" /SUBSYSTEM:CONSOLE /Machine:X64 /ERRORREPORT:QUEUE

Expand Down
90 changes: 90 additions & 0 deletions src/disasm-i.c
Expand Up @@ -100,6 +100,12 @@ void mips_disasm_i_lh(char* mnemonic,u32 length,u32 pc,mips_instruction instruct
sim_snprintf(mnemonic,length,"lh %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_lwl(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"lwl %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_lw(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
Expand All @@ -118,6 +124,12 @@ void mips_disasm_i_lhu(char* mnemonic,u32 length,u32 pc,mips_instruction instruc
sim_snprintf(mnemonic,length,"lhu %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_lwr(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"lwr %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_sb(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
Expand All @@ -130,15 +142,93 @@ void mips_disasm_i_sh(char* mnemonic,u32 length,u32 pc,mips_instruction instruct
sim_snprintf(mnemonic,length,"sh %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_swl(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"swl %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_sw(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"sw %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_swr(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"swr %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_ll(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"ll %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

void mips_disasm_i_sc(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"sc %s,%d(%s)",mips_gpr_string[instruction.i.rt],imm,mips_gpr_string[instruction.i.rs]);
}

// RegImm I-Format Instructions...
void mips_disasm_i_bltz(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"bltz %s,0x%X",mips_gpr_string[instruction.i.rs],pc+(imm<<2));
}

void mips_disasm_i_bgez(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"bgez %s,0x%X",mips_gpr_string[instruction.i.rs],pc+(imm<<2));
}

void mips_disasm_i_tgei(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"tgei %s,%d",mips_gpr_string[instruction.i.rs],imm);
}

void mips_disasm_i_tgeiu(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"tgeiu %s,%d",mips_gpr_string[instruction.i.rs],imm);
}

void mips_disasm_i_tlti(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"tlti %s,%d",mips_gpr_string[instruction.i.rs],imm);
}

void mips_disasm_i_tltiu(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"tltiu %s,%d",mips_gpr_string[instruction.i.rs],imm);
}

void mips_disasm_i_teqi(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"teqi %s,%d",mips_gpr_string[instruction.i.rs],imm);
}

void mips_disasm_i_tnei(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"tnei %s,%d",mips_gpr_string[instruction.i.rs],imm);
}

void mips_disasm_i_bltzal(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"bltzal %s,0x%X",mips_gpr_string[instruction.i.rs],pc+(imm<<2));
}

void mips_disasm_i_bgezal(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
const i32 imm=(i32)((i16)instruction.i.imm);
sim_snprintf(mnemonic,length,"bgezal %s,0x%X",mips_gpr_string[instruction.i.rs],pc+(imm<<2));
}
51 changes: 49 additions & 2 deletions src/disasm-r.c
Expand Up @@ -19,7 +19,10 @@

void mips_disasm_r_sll(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"sll %s,%s,%u",mips_gpr_string[instruction.r.rd],mips_gpr_string[instruction.r.rt],instruction.r.shamt);
if(instruction.value==0)
sim_snprintf(mnemonic,length,"nop"); // NOP instruction.
else
sim_snprintf(mnemonic,length,"sll %s,%s,%u",mips_gpr_string[instruction.r.rd],mips_gpr_string[instruction.r.rt],instruction.r.shamt);
}

void mips_disasm_r_srl(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
Expand Down Expand Up @@ -54,7 +57,10 @@ void mips_disasm_r_jr(char* mnemonic,u32 length,u32 pc,mips_instruction instruct

void mips_disasm_r_jalr(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"jalr %s",mips_gpr_string[instruction.r.rs]);
if(instruction.r.rd==31 || instruction.r.rd==0)
sim_snprintf(mnemonic,length,"jalr %s",mips_gpr_string[instruction.r.rs]);
else
sim_snprintf(mnemonic,length,"jalr %s,%s",mips_gpr_string[instruction.r.rd],mips_gpr_string[instruction.r.rs]);
}

void mips_disasm_r_movz(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
Expand Down Expand Up @@ -170,4 +176,45 @@ void mips_disasm_r_slt(char* mnemonic,u32 length,u32 pc,mips_instruction instruc
void mips_disasm_r_sltu(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"sltu %s,%s,%s",mips_gpr_string[instruction.r.rd],mips_gpr_string[instruction.r.rs],mips_gpr_string[instruction.r.rt]);
}

void mips_disasm_r_tge(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"tge %s,%s",mips_gpr_string[instruction.r.rs],mips_gpr_string[instruction.r.rt]);
}

void mips_disasm_r_tgeu(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"tgeu %s,%s",mips_gpr_string[instruction.r.rs],mips_gpr_string[instruction.r.rt]);
}

void mips_disasm_r_tlt(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"tlt %s,%s",mips_gpr_string[instruction.r.rs],mips_gpr_string[instruction.r.rt]);
}

void mips_disasm_r_tltu(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"tltu %s,%s",mips_gpr_string[instruction.r.rs],mips_gpr_string[instruction.r.rt]);
}

void mips_disasm_r_teq(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"teq %s,%s",mips_gpr_string[instruction.r.rs],mips_gpr_string[instruction.r.rt]);
}

void mips_disasm_r_tne(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"tne %s,%s",mips_gpr_string[instruction.r.rs],mips_gpr_string[instruction.r.rt]);
}

// R2-Format Instructions
void mips_disasm_r_clz(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"clz %s,%s",mips_gpr_string[instruction.r.rd],mips_gpr_string[instruction.r.rs]);
}

void mips_disasm_r_clo(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
sim_snprintf(mnemonic,length,"clo %s,%s",mips_gpr_string[instruction.r.rd],mips_gpr_string[instruction.r.rs]);
}
5 changes: 5 additions & 0 deletions src/disasm.c
Expand Up @@ -37,6 +37,11 @@ void mips_disasm_r_format(char* mnemonic,u32 length,u32 pc,mips_instruction inst
mips_disasm_r_funct[instruction.r.funct](mnemonic,length,pc,instruction);
}

void mips_disasm_r2_format(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
mips_disasm_r2_funct[instruction.r.funct](mnemonic,length,pc,instruction);
}

void mips_disasm_regimm_i_format(char* mnemonic,u32 length,u32 pc,mips_instruction instruction)
{
mips_disasm_regimm_i_funct[instruction.i.rt](mnemonic,length,pc,instruction);
Expand Down
11 changes: 10 additions & 1 deletion src/include/devkit.h
Expand Up @@ -37,4 +37,13 @@ bool unload_section(void* section);
void* alloc_page(u32 size);
bool free_page(void* address);
void* alloc_mem(u32 size);
bool free_mem(void* address);
bool free_mem(void* address);

#if defined(_msvc)
#define intrin_bt _bittest
#define intrin_bts _bittestandset
#define intrin_btr _bittestandreset
#define intrin_btc _bittestandcomplement

#define intrin_locked_xchg _InterlockedExchange
#endif

0 comments on commit 2f34872

Please sign in to comment.