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

📄 decoder.cc

📁 一个mips虚拟机非常好代码,使用C++来编写的,希望大家多学学,
💻 CC
📖 第 1 页 / 共 4 页
字号:
#include "instr.hh"#include "koala.hh"// This monster of a switch statement decodes all CPU instructions. I've// decided against an explicit jump table, as such implementation both// increases the code size and introduced additional overhead to the inner// decoder loop.// WARNING: The below code currently does not simulate any slips.// This should be fixed soon (it's fairly easy to simulate, too.)intKoala::decode(Instr instr){    if (catch_nops > 0) {	if (instr)	    nop_count = 0;	else if (++nop_count >= catch_nops) {	    msg("%d NOP instructions executed in a row. Bailing out.",		catch_nops);	    Tcl_Exit(1);	}    }    switch (opcode(instr)) {    case SPECIAL:    {	// Special instructions, decoded using the (function) field.	if (trace_level > 4) {		dump_state();	}	switch (function(instr)) {	case SLL:	{	    // Shift Left Logical ////////////////////////////////////////////	    if (rd(instr)) {		// This is optimized for gpr[0], as it comonly used as a NOP.		if (trace_level >= print_instructions)		    log("[%lx]\tsll\t%s, %s, %d", pc,			regname[rd(instr)],			regname[rt(instr)],			shamt(instr));		UInt32 x = gpr[rt(instr)];		int s = shamt(instr);		gpr[rd(instr)] = sign_extend<UInt64>(x << s, 32);	    }	    else {		if (trace_level >= print_instructions)		    log("[%lx]\tnop", pc);	    }	    return nothing_special;	}	case SRL:	{	    // Shift Right Logical ///////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsrl\t%s, %s, %d", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    shamt(instr));	    UInt32 x = zero_extend<UInt32>(gpr[rt(instr)], 32);	    int s = shamt(instr);	    gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 32);	    return nothing_special;	}	case SRA:	{	    // Shift Right Arithmetic ////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsra\t%s, %s, %d", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    shamt(instr));	    UInt32 x = zero_extend<UInt32>(gpr[rt(instr)], 32);	    int s = shamt(instr);	    gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 32 - s);	    return nothing_special;	}	case SLLV:	{	    // Shift Left Logical Variable ///////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsllv\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    regname[rs(instr)]);	    UInt32 x = gpr[rt(instr)];	    int s = bits(gpr[rs(instr)], 4, 0);	    gpr[rd(instr)] = sign_extend<UInt64>(x << s, 32);	    return nothing_special;	}	case SRLV:	{	    // Shift Right Logical Variable //////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsrlv\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    regname[rs(instr)]);	    UInt32 x = zero_extend<UInt32>(gpr[rt(instr)], 32);	    int s = bits(gpr[rs(instr)], 4, 0);	    gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 32);	    return nothing_special;	}	case SRAV:	{	    // Shift Right Arithmetic Variable ///////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsrav\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    regname[rs(instr)]);	    UInt32 x = gpr[rt(instr)];	    int s = bits(gpr[rs(instr)], 4, 0);	    gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 32 - s);	    return nothing_special;	}	case JR:	{	    // Jump Register /////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tjr\t%s", pc,		    regname[rs(instr)]);	    branch_target = gpr[rs(instr)];	    	if (pipeline == branch_delay) {		log("Illegal branch in branch delay slot at: %lx\n", pc);		assert(!"Can't handle branch in branch delay slot");	}	    return bits(branch_target, 1, 0) ? instr_addr_error :		branch_delay;	}	case JALR:	{	    // Jump And Link Register ////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tjalr\t%s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)]);	    branch_target = gpr[rs(instr)];	    gpr[31] = sign_extend<UInt64>(pc + 8, 64);	    	if (pipeline == branch_delay) {		log("Illegal branch in branch delay slot at: %lx\n", pc);		assert(!"Can't handle branch in branch delay slot");	}	    return bits(branch_target, 1, 0) ? instr_addr_error :		branch_delay;	}	case SYSCALL:	{	    // System Call ///////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsyscall", pc);	    process_syscall();	    return nothing_special;	}	case BREAK:	{	    // Breakpoint ////////////////////////////////////////////////////	    if (trace_level >= print_instructions || bits(instr, 31, 16) > 0)		log("[%lx]\tbreak\t%d", pc, bits(instr, 31, 16));#if 0	    // Enable tracing level.	    if (trace_level >= 0) {		trace_level = bits(instr, 31, 16);		if (trace_level == 666) {		    msg("BREAK 666: bailing out");		    Tcl_Exit(1);		}		msg("Trace level set to %d", trace_level);	    }	    else {		process_breakpoint();	    }#endif	    process_breakpoint();	    return nothing_special;	}	case SYNC:	{	    // Synchronize ///////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsync", pc);	    sync_bit = true;	    return nothing_special;	}	case MFHI:	{	    // Move From HI //////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tmfhi\t%s", pc,		    regname[rd(instr)]);	    gpr[rd(instr)] = hi;	    return nothing_special;	}	case MTHI:	{	    // Move To HI ////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tmthi\t%s", pc,		    regname[rs(instr)]);	    hi = gpr[rs(instr)];	    return nothing_special;	}	case MFLO:	{	    // Move From LO //////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tmflo\t%s", pc,		    regname[rd(instr)]);	    gpr[rd(instr)] = lo;	    return nothing_special;	}	case MTLO:	{	    // Move To LO ////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tmtlo\t%s", pc,		    regname[rs(instr)]);	    lo = gpr[rs(instr)];	    return nothing_special;	}	case DSLLV:	{	    // Doubleword Shift Left Logical Variable ////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tdsllv\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    regname[rs(instr)]);	    if (!allow_xinstr())		process_reserved_instruction();	    UInt64 x = gpr[rt(instr)];	    int s = bits(gpr[rs(instr)], 5, 0);	    gpr[rd(instr)] = sign_extend<UInt64>(x << s, 64);	    return nothing_special;	}	case DSRLV:	{	    // Doubleword Shift Right Logical Variable ///////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tdsrlv\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    regname[rs(instr)]);	    if (!allow_xinstr())		process_reserved_instruction();	    UInt64 x = zero_extend<UInt64>(gpr[rt(instr)], 64);	    int s = bits(gpr[rs(instr)], 5, 0);	    gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 64);	    return nothing_special;	}	case DSRAV:	{	    // Doubleword Shift Right Arithmetic Variable ////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tdsrav\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rt(instr)],		    regname[rs(instr)]);	    if (!allow_xinstr())		process_reserved_instruction();	    UInt64 x = gpr[rt(instr)];	    int s = bits(gpr[rs(instr)], 5, 0);	    gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 64 - s);	    return nothing_special;	}	case MULT:	{	    // Multiply //////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tmult\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    Int32 x = sign_extend<Int32>(gpr[rs(instr)], 32);	    Int32 y = sign_extend<Int32>(gpr[rt(instr)], 32);	    MulResult<Int32> r = multiply(x, y);	    lo = sign_extend<UInt64>(r.lo, 32);	    hi = sign_extend<UInt64>(r.hi, 32);	    return nothing_special;	}	case MULTU:	{	    // Multiply Unsigned /////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tmultu\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    UInt32 x = zero_extend<UInt32>(gpr[rs(instr)], 32);	    UInt32 y = zero_extend<UInt32>(gpr[rt(instr)], 32);	    MulResult<UInt32> r = multiply(x, y);	    lo = sign_extend<UInt64>(r.lo, 32);	    hi = sign_extend<UInt64>(r.hi, 32);	    return nothing_special;	}	case DIV:	{	    // Divide ////////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tdiv\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    Int32 y = sign_extend<Int32>(gpr[rt(instr)], 32);	    if (y) {		Int32 x = sign_extend<Int32>(gpr[rs(instr)], 32);		DivResult<Int32> r = divide(x, y);		lo = sign_extend<UInt64>(r.quot, 32);		hi = sign_extend<UInt64>(r.rem, 32);	    }	    return nothing_special;	}	case DIVU:	{	    // Divide Unsigned ///////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tdivu\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    UInt32 y = zero_extend<UInt32>(gpr[rt(instr)], 32);	    if (y) {		UInt32 x = zero_extend<UInt32>(gpr[rs(instr)], 32);		DivResult<UInt32> r = divide(x, y);		lo = sign_extend<UInt64>(r.quot, 32);		hi = sign_extend<UInt64>(r.rem, 32);	    }	    return nothing_special;	}	case DMULT:	{	    // Doubleword Multiply ///////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tdmult\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    if (!allow_xinstr())		process_reserved_instruction();	    Int64 x = gpr[rs(instr)];	    Int64 y = gpr[rt(instr)];	    MulResult<Int64> r = multiply(x, y);	    lo = sign_extend<UInt64>(r.lo, 64);	    hi = sign_extend<UInt64>(r.hi, 64);	    return nothing_special;	}	case DMULTU:	{	    // Doubleword Multiply Unsigned //////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tdmultu\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    if (!allow_xinstr())		process_reserved_instruction();	    UInt64 x = zero_extend<UInt64>(gpr[rs(instr)], 64);	    UInt64 y = zero_extend<UInt64>(gpr[rt(instr)], 64);	    MulResult<UInt64> r = multiply(x, y);	    lo = sign_extend<UInt64>(r.lo, 64);	    hi = sign_extend<UInt64>(r.hi, 64);	    return nothing_special;	}	case DDIV:	{	    // Doubleword Divide /////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tddiv\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    if (!allow_xinstr())		process_reserved_instruction();	    Int64 y = gpr[rt(instr)];	    if (y) {		Int64 x = gpr[rs(instr)];		DivResult<Int64> r = divide(x, y);		lo = sign_extend<UInt64>(r.quot, 64);		hi = sign_extend<UInt64>(r.rem, 64);	    }	    return nothing_special;	}	case DDIVU:	{	    // Doubleword Divide Unsigned ////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tddivu\t%s, %s", pc,		    regname[rs(instr)],		    regname[rt(instr)]);	    if (!allow_xinstr())		process_reserved_instruction();	    UInt64 y = zero_extend<UInt64>(gpr[rt(instr)], 64);	    if (y) {		UInt64 x = zero_extend<UInt64>(gpr[rs(instr)], 64);		DivResult<UInt64> r = divide(x, y);		lo = sign_extend<UInt64>(r.quot, 64);		hi = sign_extend<UInt64>(r.rem, 64);	    }	    return nothing_special;	}	case ADD:	    {	    // Add ///////////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tadd\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    UInt32 x = gpr[rs(instr)];	    UInt32 y = gpr[rt(instr)];	    UInt32 z = x + y;	    // Overflow occurs is sign(x) == sign(y) != sign(z).	    if (bit(x ^ y, 31) == 0 && bit(x ^ z, 31) != 0)		process_integer_overflow();	    gpr[rd(instr)] = sign_extend<UInt64>(z, 32);	    return nothing_special;	}	case ADDU:	{	    // Add Unsigned //////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\taddu\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    UInt32 x = gpr[rs(instr)];	    UInt32 y = gpr[rt(instr)];	    gpr[rd(instr)] = sign_extend<UInt64>(x + y, 32);	    return nothing_special;	}	case SUB:	{	    // Subtract //////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsub\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    Int32 x = zero_extend<UInt32>(gpr[rs(instr)], 32);	    Int32 y = zero_extend<UInt32>(gpr[rt(instr)], 32);	    Int32 z = UInt32(x) - UInt32(y);	    if ((y < 0 && z < x) || (y > 0 && z > x))		process_integer_overflow();	    gpr[rd(instr)] = sign_extend<UInt64>(z, 32);	    return nothing_special;	}	case SUBU:	{	    // Subtract Unsigned /////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tsubu\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    UInt32 x = zero_extend<UInt32>(gpr[rs(instr)], 32);	    UInt32 y = zero_extend<UInt32>(gpr[rt(instr)], 32);	    gpr[rd(instr)] = sign_extend<UInt64>(x - y, 32);	    return nothing_special;	}	case AND:	{	    // And ///////////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tand\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    gpr[rd(instr)] = gpr[rs(instr)] & gpr[rt(instr)];	    return nothing_special;	}	case OR:	{	    // Or ////////////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tor\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    gpr[rd(instr)] = gpr[rs(instr)] | gpr[rt(instr)];	    return nothing_special;	}	case XOR:	{	    // Exclusive Or //////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\txor\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    gpr[rd(instr)] = gpr[rs(instr)] ^ gpr[rt(instr)];	    return nothing_special;	}	case NOR:	{	    // Nor ///////////////////////////////////////////////////////////	    if (trace_level >= print_instructions)		log("[%lx]\tnor\t%s, %s, %s", pc,		    regname[rd(instr)],		    regname[rs(instr)],		    regname[rt(instr)]);	    gpr[rd(instr)] = ~(gpr[rs(instr)] | gpr[rt(instr)]);	    return nothing_special;	}	case SLT:	{

⌨️ 快捷键说明

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