Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1347 lines (1175 sloc) 28.6 KB

Mipsgen javascript code generator

The mipsgen javascript code generator generates the core routines for a javascript-based MIPS disassembler. The code for that disassembler is located in scripts/mipsdis.js.

The bulk of the work done by the code generator is generating dispatch and decoder functions.

An example of a generated dispatch function:

function decode_OPCODE(pc, op)
{
    switch (getopcode(op))
    {
        case 0:
            return decode_SPC1(pc, op);
            break;
        case 1:
            return decode_R(pc, op);
            break;
        case 2:
            return decode_j(pc, op);
            break;
        case 3:
            return decode_jal(pc, op);
            break;
        case 4:
            return decode_beq(pc, op);
            break;
    ...
    }
}

An example of a generated decoder:

function decode_jal(pc, op)
{
    ok = check_opcode(op, 0xfc000000, 0x0c000000);
    if (!ok) return 'illegal';

    return sprintf("jal 0x%x", gettarget(pc,op));
}

The generated code expects the host code to implement the following utility routines :

// Packed field extraction functions:

function getopcode(op)
function getfunction(op)
function getrt(op)
function getrs(op)
function getrd(op)
function gettarget(pc, op)
function getbroff(pc, op)
function getsimm(op) 
function getimm(op)
function getoffset(op)
function getbase(op)
function getcacheop(op)
function getprefhint(op)
function getsa(op)
function getbc1(op)
function getbc2(op)
function getsyscode(op)
function getstype(op)
function gettrapcode(op)
function getsel(op)
function getwaitcode(op)

// Instruction validation functions:

function check_opcode(op, mask, value)
function check_cl(rt, rd)
function check_jalr(rs, rd)

A full copy of the generated javascript code is included below, so that people browsing the project, or having trouble with the autogen can see what it looks like.

/*
 * This file contains autogenerated routines for dispatching and disassembling
 * MIPS opcodes.
 *
 * The code has been generated by mipsgen.
 *
 * See scripts/mipsgen.rb for the code generator framework.
 * See codegen/jsgen.rb for javascript specific information.
 */

function decode_j(pc, op)
{
    return sprintf("j 0x%x", gettarget(pc,op));
}

function decode_jal(pc, op)
{
    return sprintf("jal 0x%x", gettarget(pc,op));
}

function decode_beq(pc, op)
{
    return sprintf("beq $%d,$%d,0x%x", getrs(op), getrt(op), getbroff(pc,op));
}

function decode_bne(pc, op)
{
    return sprintf("bne $%d,$%d,0x%x", getrs(op), getrt(op), getbroff(pc,op));
}

function decode_blez(pc, op)
{
    ok = check_opcode(op, 0xfc1f0000, 0x18000000);
    if (!ok) return 'illegal';

    return sprintf("blez $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bgtz(pc, op)
{
    ok = check_opcode(op, 0xfc1f0000, 0x1c000000);
    if (!ok) return 'illegal';

    return sprintf("bgtz $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_addi(pc, op)
{
    return sprintf("addi $%d,$%d,%d", getrt(op), getrs(op), getsimm(op));
}

function decode_addiu(pc, op)
{
    return sprintf("addiu $%d,$%d,%d", getrt(op), getrs(op), getsimm(op));
}

function decode_slti(pc, op)
{
    return sprintf("slti $%d,$%d,%d", getrt(op), getrs(op), getsimm(op));
}

function decode_sltiu(pc, op)
{
    return sprintf("sltiu $%d,$%d,%d", getrt(op), getrs(op), getsimm(op));
}

function decode_andi(pc, op)
{
    return sprintf("andi $%d,$%d,0x%x", getrt(op), getrs(op), getimm(op));
}

function decode_ori(pc, op)
{
    return sprintf("ori $%d,$%d,0x%x", getrt(op), getrs(op), getimm(op));
}

function decode_xori(pc, op)
{
    return sprintf("xori $%d,$%d,0x%x", getrt(op), getrs(op), getimm(op));
}

function decode_lui(pc, op)
{
    ok = check_opcode(op, 0xffe00000, 0x3c000000);
    if (!ok) return 'illegal';

    return sprintf("lui $%d,0x%x", getrt(op), getimm(op));
}

function decode_beql(pc, op)
{
    return sprintf("beql $%d,$%d,0x%x", getrs(op), getrt(op), getbroff(pc,op));
}

function decode_bnel(pc, op)
{
    return sprintf("bnel $%d,$%d,0x%x", getrs(op), getrt(op), getbroff(pc,op));
}

function decode_blezl(pc, op)
{
    ok = check_opcode(op, 0xfc1f0000, 0x58000000);
    if (!ok) return 'illegal';

    return sprintf("blezl $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bgtzl(pc, op)
{
    ok = check_opcode(op, 0xfc1f0000, 0x5c000000);
    if (!ok) return 'illegal';

    return sprintf("bgtzl $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_lb(pc, op)
{
    return sprintf("lb $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_lh(pc, op)
{
    return sprintf("lh $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_lwl(pc, op)
{
    return sprintf("lwl $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_lw(pc, op)
{
    return sprintf("lw $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_lbu(pc, op)
{
    return sprintf("lbu $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_lhu(pc, op)
{
    return sprintf("lhu $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_lwr(pc, op)
{
    return sprintf("lwr $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_sb(pc, op)
{
    return sprintf("sb $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_sh(pc, op)
{
    return sprintf("sh $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_swl(pc, op)
{
    return sprintf("swl $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_sw(pc, op)
{
    return sprintf("sw $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_swr(pc, op)
{
    return sprintf("swr $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_cache(pc, op)
{
    return sprintf("cache 0x%x,%d($%d)", getcacheop(op), getoffset(op), getbase(op));
}

function decode_ll(pc, op)
{
    return sprintf("ll $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_pref(pc, op)
{
    return sprintf("pref 0x%x,%d($%d)", getprefhint(op), getoffset(op), getbase(op));
}

function decode_sc(pc, op)
{
    return sprintf("sc $%d,%d($%d)", getrt(op), getoffset(op), getbase(op));
}

function decode_sll(pc, op)
{
    ok = check_opcode(op, 0xffe0003f, 0x00000000);
    if (!ok) return 'illegal';

    return sprintf("sll $%d,$%d,0x%x", getrd(op), getrt(op), getsa(op));
}

function decode_srl(pc, op)
{
    ok = check_opcode(op, 0xffe0003f, 0x00000002);
    if (!ok) return 'illegal';

    return sprintf("srl $%d,$%d,0x%x", getrd(op), getrt(op), getsa(op));
}

function decode_sra(pc, op)
{
    ok = check_opcode(op, 0xffe0003f, 0x00000003);
    if (!ok) return 'illegal';

    return sprintf("sra $%d,$%d,0x%x", getrd(op), getrt(op), getsa(op));
}

function decode_sllv(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000004);
    if (!ok) return 'illegal';

    return sprintf("sllv $%d,$%d,$%d", getrd(op), getrt(op), getrs(op));
}

function decode_srlv(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000006);
    if (!ok) return 'illegal';

    return sprintf("srlv $%d,$%d,$%d", getrd(op), getrt(op), getrs(op));
}

function decode_srav(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000007);
    if (!ok) return 'illegal';

    return sprintf("srav $%d,$%d,$%d", getrd(op), getrt(op), getrs(op));
}

function decode_jr(pc, op)
{
    ok = check_opcode(op, 0xfc1fffff, 0x00000008);
    if (!ok) return 'illegal';

    return sprintf("jr $%d", getrs(op));
}

function decode_jalr(pc, op)
{
    ok = check_opcode(op, 0xfc1f07ff, 0x00000009) && check_jalr(getrs(op), getrd(op));
    if (!ok) return 'illegal';

    return sprintf("jalr $%d,$%d", getrd(op), getrs(op));
}

function decode_movz(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x0000000a);
    if (!ok) return 'illegal';

    return sprintf("movz $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_movn(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x0000000b);
    if (!ok) return 'illegal';

    return sprintf("movn $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_syscall(pc, op)
{
    return sprintf("syscall 0x%x", getsyscode(op));
}

function decode_break(pc, op)
{
    return sprintf("break 0x%x,0x%x", getbc1(op), getbc2(op));
}

function decode_sync(pc, op)
{
    ok = check_opcode(op, 0xfffff83f, 0x0000000f);
    if (!ok) return 'illegal';

    return sprintf("sync 0x%x", getstype(op));
}

function decode_mfhi(pc, op)
{
    ok = check_opcode(op, 0xffff07ff, 0x00000010);
    if (!ok) return 'illegal';

    return sprintf("mfhi $%d", getrd(op));
}

function decode_mthi(pc, op)
{
    ok = check_opcode(op, 0xfc1fffff, 0x00000011);
    if (!ok) return 'illegal';

    return sprintf("mthi $%d", getrs(op));
}

function decode_mflo(pc, op)
{
    ok = check_opcode(op, 0xffff07ff, 0x00000012);
    if (!ok) return 'illegal';

    return sprintf("mflo $%d", getrd(op));
}

function decode_mtlo(pc, op)
{
    ok = check_opcode(op, 0xfc1fffff, 0x00000013);
    if (!ok) return 'illegal';

    return sprintf("mtlo $%d", getrs(op));
}

function decode_mult(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x00000018);
    if (!ok) return 'illegal';

    return sprintf("mult $%d,$%d", getrs(op), getrt(op));
}

function decode_multu(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x00000019);
    if (!ok) return 'illegal';

    return sprintf("multu $%d,$%d", getrs(op), getrt(op));
}

function decode_div(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x0000001a);
    if (!ok) return 'illegal';

    return sprintf("div $%d,$%d", getrs(op), getrt(op));
}

function decode_divu(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x0000001b);
    if (!ok) return 'illegal';

    return sprintf("divu $%d,$%d", getrs(op), getrt(op));
}

function decode_add(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000020);
    if (!ok) return 'illegal';

    return sprintf("add $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_addu(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000021);
    if (!ok) return 'illegal';

    return sprintf("addu $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_sub(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000022);
    if (!ok) return 'illegal';

    return sprintf("sub $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_subu(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000023);
    if (!ok) return 'illegal';

    return sprintf("subu $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_and(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000024);
    if (!ok) return 'illegal';

    return sprintf("and $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_or(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000025);
    if (!ok) return 'illegal';

    return sprintf("or $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_xor(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000026);
    if (!ok) return 'illegal';

    return sprintf("xor $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_nor(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x00000027);
    if (!ok) return 'illegal';

    return sprintf("nor $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_slt(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x0000002a);
    if (!ok) return 'illegal';

    return sprintf("slt $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_sltu(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x0000002b);
    if (!ok) return 'illegal';

    return sprintf("sltu $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_tge(pc, op)
{
    return sprintf("tge $%d,$%d,0x%x", getrs(op), getrt(op), gettrapcode(op));
}

function decode_tgeu(pc, op)
{
    return sprintf("tgeu $%d,$%d,0x%x", getrs(op), getrt(op), gettrapcode(op));
}

function decode_tlt(pc, op)
{
    return sprintf("tlt $%d,$%d,0x%x", getrs(op), getrt(op), gettrapcode(op));
}

function decode_tltu(pc, op)
{
    return sprintf("tltu $%d,$%d,0x%x", getrs(op), getrt(op), gettrapcode(op));
}

function decode_teq(pc, op)
{
    return sprintf("teq $%d,$%d,0x%x", getrs(op), getrt(op), gettrapcode(op));
}

function decode_tne(pc, op)
{
    return sprintf("tne $%d,$%d,0x%x", getrs(op), getrt(op), gettrapcode(op));
}

function decode_madd(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x70000000);
    if (!ok) return 'illegal';

    return sprintf("madd $%d,$%d", getrs(op), getrt(op));
}

function decode_maddu(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x70000001);
    if (!ok) return 'illegal';

    return sprintf("maddu $%d,$%d", getrs(op), getrt(op));
}

function decode_mul(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x70000002);
    if (!ok) return 'illegal';

    return sprintf("mul $%d,$%d,$%d", getrd(op), getrs(op), getrt(op));
}

function decode_msub(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x70000004);
    if (!ok) return 'illegal';

    return sprintf("msub $%d,$%d", getrs(op), getrt(op));
}

function decode_msubu(pc, op)
{
    ok = check_opcode(op, 0xfc00ffff, 0x70000005);
    if (!ok) return 'illegal';

    return sprintf("msubu $%d,$%d", getrs(op), getrt(op));
}

function decode_clz(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x70000020) && check_cl(getrt(op), getrd(op));
    if (!ok) return 'illegal';

    return sprintf("clz $%d,$%d", getrd(op), getrs(op));
}

function decode_clo(pc, op)
{
    ok = check_opcode(op, 0xfc0007ff, 0x70000021) && check_cl(getrt(op), getrd(op));
    if (!ok) return 'illegal';

    return sprintf("clo $%d,$%d", getrd(op), getrs(op));
}

function decode_sdbbp(pc, op)
{
    return sprintf("sdbbp 0x%x", getsyscode(op));
}

function decode_bltz(pc, op)
{
    return sprintf("bltz $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bgez(pc, op)
{
    return sprintf("bgez $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bltzl(pc, op)
{
    return sprintf("bltzl $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bgezl(pc, op)
{
    return sprintf("bgezl $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_tgei(pc, op)
{
    return sprintf("tgei $%d,%d", getrs(op), getsimm(op));
}

function decode_tgeiu(pc, op)
{
    return sprintf("tgeiu $%d,%d", getrs(op), getsimm(op));
}

function decode_tlti(pc, op)
{
    return sprintf("tlti $%d,%d", getrs(op), getsimm(op));
}

function decode_tltiu(pc, op)
{
    return sprintf("tltiu $%d,%d", getrs(op), getsimm(op));
}

function decode_teqi(pc, op)
{
    return sprintf("teqi $%d,%d", getrs(op), getsimm(op));
}

function decode_tnei(pc, op)
{
    return sprintf("tnei $%d,%d", getrs(op), getsimm(op));
}

function decode_bltzal(pc, op)
{
    return sprintf("bltzal $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bgezal(pc, op)
{
    return sprintf("bgezal $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bltzall(pc, op)
{
    return sprintf("bltzall $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_bgezall(pc, op)
{
    return sprintf("bgezall $%d,0x%x", getrs(op), getbroff(pc,op));
}

function decode_mfc0(pc, op)
{
    ok = check_opcode(op, 0xffe007f8, 0x40000000);
    if (!ok) return 'illegal';

    return sprintf("mfc0 $%d,$%d,%d", getrt(op), getrd(op), getsel(op));
}

function decode_mtc0(pc, op)
{
    ok = check_opcode(op, 0xffe007f8, 0x40800000);
    if (!ok) return 'illegal';

    return sprintf("mtc0 $%d,$%d,%d", getrt(op), getrd(op), getsel(op));
}

function decode_tlbr(pc, op)
{
    ok = check_opcode(op, 0xffffffff, 0x42000001);
    if (!ok) return 'illegal';

    return sprintf("tlbr");
}

function decode_tlbwi(pc, op)
{
    ok = check_opcode(op, 0xffffffff, 0x42000002);
    if (!ok) return 'illegal';

    return sprintf("tlbwi");
}

function decode_tlbwr(pc, op)
{
    ok = check_opcode(op, 0xffffffff, 0x42000006);
    if (!ok) return 'illegal';

    return sprintf("tlbwr");
}

function decode_tlbp(pc, op)
{
    ok = check_opcode(op, 0xffffffff, 0x42000008);
    if (!ok) return 'illegal';

    return sprintf("tlbp");
}

function decode_eret(pc, op)
{
    ok = check_opcode(op, 0xffffffff, 0x42000018);
    if (!ok) return 'illegal';

    return sprintf("eret");
}

function decode_deret(pc, op)
{
    ok = check_opcode(op, 0xffffffff, 0x4200001f);
    if (!ok) return 'illegal';

    return sprintf("deret");
}

function decode_wait(pc, op)
{
    return sprintf("wait 0x%x", getwaitcode(op));
}

function decode_OPCODE(pc, op)
{
    switch (getopcode(op))
    {
        case 0:
            return decode_SPC1(pc, op);
            break;
        case 1:
            return decode_R(pc, op);
            break;
        case 2:
            return decode_j(pc, op);
            break;
        case 3:
            return decode_jal(pc, op);
            break;
        case 4:
            return decode_beq(pc, op);
            break;
        case 5:
            return decode_bne(pc, op);
            break;
        case 6:
            return decode_blez(pc, op);
            break;
        case 7:
            return decode_bgtz(pc, op);
            break;
        case 8:
            return decode_addi(pc, op);
            break;
        case 9:
            return decode_addiu(pc, op);
            break;
        case 10:
            return decode_slti(pc, op);
            break;
        case 11:
            return decode_sltiu(pc, op);
            break;
        case 12:
            return decode_andi(pc, op);
            break;
        case 13:
            return decode_ori(pc, op);
            break;
        case 14:
            return decode_xori(pc, op);
            break;
        case 15:
            return decode_lui(pc, op);
            break;
        case 16:
            return decode_COP0(pc, op);
            break;
        case 17:
        case 18:
        case 19:
        case 49:
        case 50:
        case 53:
        case 54:
        case 57:
        case 58:
        case 61:
        case 62:
            return decode_unusable(pc, op);
            break;
        case 20:
            return decode_beql(pc, op);
            break;
        case 21:
            return decode_bnel(pc, op);
            break;
        case 22:
            return decode_blezl(pc, op);
            break;
        case 23:
            return decode_bgtzl(pc, op);
            break;
        case 24:
        case 25:
        case 26:
        case 27:
        case 29:
        case 30:
        case 31:
        case 39:
        case 44:
        case 45:
        case 52:
        case 55:
        case 59:
        case 60:
        case 63:
            return decode_reserved(pc, op);
            break;
        case 28:
            return decode_SPC2(pc, op);
            break;
        case 32:
            return decode_lb(pc, op);
            break;
        case 33:
            return decode_lh(pc, op);
            break;
        case 34:
            return decode_lwl(pc, op);
            break;
        case 35:
            return decode_lw(pc, op);
            break;
        case 36:
            return decode_lbu(pc, op);
            break;
        case 37:
            return decode_lhu(pc, op);
            break;
        case 38:
            return decode_lwr(pc, op);
            break;
        case 40:
            return decode_sb(pc, op);
            break;
        case 41:
            return decode_sh(pc, op);
            break;
        case 42:
            return decode_swl(pc, op);
            break;
        case 43:
            return decode_sw(pc, op);
            break;
        case 46:
            return decode_swr(pc, op);
            break;
        case 47:
            return decode_cache(pc, op);
            break;
        case 48:
            return decode_ll(pc, op);
            break;
        case 51:
            return decode_pref(pc, op);
            break;
        case 56:
            return decode_sc(pc, op);
            break;
    }
}

function decode_SPC1(pc, op)
{
    switch (getfunction(op))
    {
        case 0:
            return decode_sll(pc, op);
            break;
        case 1:
            return decode_unusable(pc, op);
            break;
        case 2:
            return decode_srl(pc, op);
            break;
        case 3:
            return decode_sra(pc, op);
            break;
        case 4:
            return decode_sllv(pc, op);
            break;
        case 5:
        case 14:
        case 20:
        case 21:
        case 22:
        case 23:
        case 28:
        case 29:
        case 30:
        case 31:
        case 40:
        case 41:
        case 44:
        case 45:
        case 46:
        case 47:
        case 53:
        case 55:
        case 56:
        case 57:
        case 58:
        case 59:
        case 60:
        case 61:
        case 62:
        case 63:
            return decode_reserved(pc, op);
            break;
        case 6:
            return decode_srlv(pc, op);
            break;
        case 7:
            return decode_srav(pc, op);
            break;
        case 8:
            return decode_jr(pc, op);
            break;
        case 9:
            return decode_jalr(pc, op);
            break;
        case 10:
            return decode_movz(pc, op);
            break;
        case 11:
            return decode_movn(pc, op);
            break;
        case 12:
            return decode_syscall(pc, op);
            break;
        case 13:
            return decode_break(pc, op);
            break;
        case 15:
            return decode_sync(pc, op);
            break;
        case 16:
            return decode_mfhi(pc, op);
            break;
        case 17:
            return decode_mthi(pc, op);
            break;
        case 18:
            return decode_mflo(pc, op);
            break;
        case 19:
            return decode_mtlo(pc, op);
            break;
        case 24:
            return decode_mult(pc, op);
            break;
        case 25:
            return decode_multu(pc, op);
            break;
        case 26:
            return decode_div(pc, op);
            break;
        case 27:
            return decode_divu(pc, op);
            break;
        case 32:
            return decode_add(pc, op);
            break;
        case 33:
            return decode_addu(pc, op);
            break;
        case 34:
            return decode_sub(pc, op);
            break;
        case 35:
            return decode_subu(pc, op);
            break;
        case 36:
            return decode_and(pc, op);
            break;
        case 37:
            return decode_or(pc, op);
            break;
        case 38:
            return decode_xor(pc, op);
            break;
        case 39:
            return decode_nor(pc, op);
            break;
        case 42:
            return decode_slt(pc, op);
            break;
        case 43:
            return decode_sltu(pc, op);
            break;
        case 48:
            return decode_tge(pc, op);
            break;
        case 49:
            return decode_tgeu(pc, op);
            break;
        case 50:
            return decode_tlt(pc, op);
            break;
        case 51:
            return decode_tltu(pc, op);
            break;
        case 52:
            return decode_teq(pc, op);
            break;
        case 54:
            return decode_tne(pc, op);
            break;
    }
}

function decode_SPC2(pc, op)
{
    switch (getfunction(op))
    {
        case 0:
            return decode_madd(pc, op);
            break;
        case 1:
            return decode_maddu(pc, op);
            break;
        case 2:
            return decode_mul(pc, op);
            break;
        case 3:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29:
        case 30:
        case 31:
        case 34:
        case 35:
        case 36:
        case 37:
        case 38:
        case 39:
        case 40:
        case 41:
        case 42:
        case 43:
        case 44:
        case 45:
        case 46:
        case 47:
        case 48:
        case 49:
        case 50:
        case 51:
        case 52:
        case 53:
        case 54:
        case 55:
        case 56:
        case 57:
        case 58:
        case 59:
        case 60:
        case 61:
        case 62:
            return decode_reserved(pc, op);
            break;
        case 4:
            return decode_msub(pc, op);
            break;
        case 5:
            return decode_msubu(pc, op);
            break;
        case 32:
            return decode_clz(pc, op);
            break;
        case 33:
            return decode_clo(pc, op);
            break;
        case 63:
            return decode_sdbbp(pc, op);
            break;
    }
}

function decode_R(pc, op)
{
    switch (getrt(op))
    {
        case 0:
            return decode_bltz(pc, op);
            break;
        case 1:
            return decode_bgez(pc, op);
            break;
        case 2:
            return decode_bltzl(pc, op);
            break;
        case 3:
            return decode_bgezl(pc, op);
            break;
        case 4:
        case 5:
        case 6:
        case 7:
        case 13:
        case 15:
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29:
        case 30:
        case 31:
            return decode_reserved(pc, op);
            break;
        case 8:
            return decode_tgei(pc, op);
            break;
        case 9:
            return decode_tgeiu(pc, op);
            break;
        case 10:
            return decode_tlti(pc, op);
            break;
        case 11:
            return decode_tltiu(pc, op);
            break;
        case 12:
            return decode_teqi(pc, op);
            break;
        case 14:
            return decode_tnei(pc, op);
            break;
        case 16:
            return decode_bltzal(pc, op);
            break;
        case 17:
            return decode_bgezal(pc, op);
            break;
        case 18:
            return decode_bltzall(pc, op);
            break;
        case 19:
            return decode_bgezall(pc, op);
            break;
    }
}

function decode_COP0(pc, op)
{
    switch (getrs(op))
    {
        case 0:
            return decode_mfc0(pc, op);
            break;
        case 1:
        case 2:
        case 3:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
            return decode_reserved(pc, op);
            break;
        case 4:
            return decode_mtc0(pc, op);
            break;
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29:
        case 30:
        case 31:
            return decode_CO(pc, op);
            break;
    }
}

function decode_CO(pc, op)
{
    switch (getfunction(op))
    {
        case 0:
        case 3:
        case 4:
        case 5:
        case 7:
        case 9:
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
        case 22:
        case 23:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29:
        case 30:
        case 33:
        case 34:
        case 35:
        case 36:
        case 37:
        case 38:
        case 39:
        case 40:
        case 41:
        case 42:
        case 43:
        case 44:
        case 45:
        case 46:
        case 47:
        case 48:
        case 49:
        case 50:
        case 51:
        case 52:
        case 53:
        case 54:
        case 55:
        case 56:
        case 57:
        case 58:
        case 59:
        case 60:
        case 61:
        case 62:
        case 63:
            return decode_reserved(pc, op);
            break;
        case 1:
            return decode_tlbr(pc, op);
            break;
        case 2:
            return decode_tlbwi(pc, op);
            break;
        case 6:
            return decode_tlbwr(pc, op);
            break;
        case 8:
            return decode_tlbp(pc, op);
            break;
        case 24:
            return decode_eret(pc, op);
            break;
        case 31:
            return decode_deret(pc, op);
            break;
        case 32:
            return decode_wait(pc, op);
            break;
    }
}