The mipsgen C code generator generates the core routines for a C-based MIPS disassembler. The code for that disassembler is located in c_disasm/mipsdis.c.
The bulk of the work done by the code generator is generating dispatch and decoder functions.
An example of a generated dispatch function:
void decode_OPCODE(MipsEmu* emu, uint32_t op)
{
switch (getopcode(op))
{
case 0:
decode_SPC1(emu, op);
break;
case 1:
decode_R(emu, op);
break;
case 2:
decode_j(emu, op);
break;
case 3:
decode_jal(emu, op);
break;
// ...
}
}An example of a generated decoder:
static void decode_jal(MipsEmu* emu, uint32_t op)
{
if (!(check_opcode(op, 0xfc000000, 0x0c000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(output,n,"jal 0x%x",gettarget(pc,op));
}The generated code expects the host code to implement the following utility routines:
// error checking routines:
static int check_opcode(uint32_t op, uint32_t mask, uint32_t value);
static int check_cl(uint32_t rt, uint32_t rd);
static int check_jalr(uint32_t rs, uint32_t rd);
// exception handling routines:
static void decode_illegal(char* outbuf, size_t n, uint32_t addr,
uint32_t opcode);
static void decode_reserved(char* outbuf, size_t n, uint32_t addr,
uint32_t opcode);
// packed field extraction routines:
static uint32_t getopcode(uint32_t op);
static uint32_t getfunction(uint32_t op);
static uint32_t getrt(uint32_t op);
static uint32_t getrs(uint32_t op);
static uint32_t getrd(uint32_t op);
static uint32_t gettarget(uint32_t pc, uint32_t op);
static uint32_t getbroff(uint32_t pc, uint32_t op);
static int32_t getsimm(uint32_t op);
static uint32_t getimm(uint32_t op);
static int32_t getoffset(uint32_t op);
static uint32_t getbase(uint32_t op);
static uint32_t getcacheop(uint32_t op);
static uint32_t getprefhint(uint32_t op);
static uint32_t getsa(uint32_t op);
static uint32_t getsyscode(uint32_t op);
static uint32_t getstype(uint32_t op);
static uint32_t gettrapcode(uint32_t op);
static uint32_t getsel(uint32_t op);
static uint32_t getwaitcode(uint32_t op);A full copy of the generated C 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/cgen.rb for C specific information.
*/
static void decode_j(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"j 0x%x",gettarget(pc,op));
}
static void decode_jal(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"jal 0x%x",gettarget(pc,op));
}
static void decode_beq(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"beq $%d,$%d,0x%x",getrs(op),getrt(op),getbroff(pc,op));
}
static void decode_bne(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bne $%d,$%d,0x%x",getrs(op),getrt(op),getbroff(pc,op));
}
static void decode_blez(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1f0000, 0x18000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"blez $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bgtz(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1f0000, 0x1c000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"bgtz $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_addi(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"addi $%d,$%d,%d",getrt(op),getrs(op),getsimm(op));
}
static void decode_addiu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"addiu $%d,$%d,%d",getrt(op),getrs(op),getsimm(op));
}
static void decode_slti(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"slti $%d,$%d,%d",getrt(op),getrs(op),getsimm(op));
}
static void decode_sltiu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"sltiu $%d,$%d,%d",getrt(op),getrs(op),getsimm(op));
}
static void decode_andi(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"andi $%d,$%d,0x%x",getrt(op),getrs(op),getimm(op));
}
static void decode_ori(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"ori $%d,$%d,0x%x",getrt(op),getrs(op),getimm(op));
}
static void decode_xori(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"xori $%d,$%d,0x%x",getrt(op),getrs(op),getimm(op));
}
static void decode_lui(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffe00000, 0x3c000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"lui $%d,0x%x",getrt(op),getimm(op));
}
static void decode_beql(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"beql $%d,$%d,0x%x",getrs(op),getrt(op),getbroff(pc,op));
}
static void decode_bnel(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bnel $%d,$%d,0x%x",getrs(op),getrt(op),getbroff(pc,op));
}
static void decode_blezl(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1f0000, 0x58000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"blezl $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bgtzl(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1f0000, 0x5c000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"bgtzl $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_lb(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"lb $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_lh(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"lh $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_lwl(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"lwl $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_lw(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"lw $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_lbu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"lbu $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_lhu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"lhu $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_lwr(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"lwr $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_sb(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"sb $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_sh(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"sh $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_swl(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"swl $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_sw(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"sw $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_swr(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"swr $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_cache(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"cache 0x%x,%d($%d)",getcacheop(op),getoffset(op),getbase(op));
}
static void decode_ll(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"ll $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_pref(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"pref 0x%x,%d($%d)",getprefhint(op),getoffset(op),getbase(op));
}
static void decode_sc(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"sc $%d,%d($%d)",getrt(op),getoffset(op),getbase(op));
}
static void decode_sll(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffe0003f, 0x00000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"sll $%d,$%d,0x%x",getrd(op),getrt(op),getsa(op));
}
static void decode_srl(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffe0003f, 0x00000002)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"srl $%d,$%d,0x%x",getrd(op),getrt(op),getsa(op));
}
static void decode_sra(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffe0003f, 0x00000003)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"sra $%d,$%d,0x%x",getrd(op),getrt(op),getsa(op));
}
static void decode_sllv(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000004)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"sllv $%d,$%d,$%d",getrd(op),getrt(op),getrs(op));
}
static void decode_srlv(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000006)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"srlv $%d,$%d,$%d",getrd(op),getrt(op),getrs(op));
}
static void decode_srav(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000007)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"srav $%d,$%d,$%d",getrd(op),getrt(op),getrs(op));
}
static void decode_jr(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1fffff, 0x00000008)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"jr $%d",getrs(op));
}
static void decode_jalr(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1f07ff, 0x00000009)&&check_jalr(getrs(op), getrd(op))))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"jalr $%d,$%d",getrd(op),getrs(op));
}
static void decode_movz(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x0000000a)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"movz $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_movn(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x0000000b)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"movn $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_syscall(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"syscall 0x%x",getsyscode(op));
}
static void decode_break(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"break 0x%x,0x%x",getbc1(op),getbc2(op));
}
static void decode_sync(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfffff83f, 0x0000000f)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"sync 0x%x",getstype(op));
}
static void decode_mfhi(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffff07ff, 0x00000010)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mfhi $%d",getrd(op));
}
static void decode_mthi(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1fffff, 0x00000011)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mthi $%d",getrs(op));
}
static void decode_mflo(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffff07ff, 0x00000012)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mflo $%d",getrd(op));
}
static void decode_mtlo(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc1fffff, 0x00000013)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mtlo $%d",getrs(op));
}
static void decode_mult(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x00000018)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mult $%d,$%d",getrs(op),getrt(op));
}
static void decode_multu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x00000019)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"multu $%d,$%d",getrs(op),getrt(op));
}
static void decode_div(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x0000001a)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"div $%d,$%d",getrs(op),getrt(op));
}
static void decode_divu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x0000001b)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"divu $%d,$%d",getrs(op),getrt(op));
}
static void decode_add(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000020)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"add $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_addu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000021)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"addu $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_sub(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000022)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"sub $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_subu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000023)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"subu $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_and(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000024)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"and $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_or(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000025)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"or $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_xor(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000026)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"xor $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_nor(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x00000027)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"nor $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_slt(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x0000002a)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"slt $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_sltu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x0000002b)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"sltu $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_tge(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tge $%d,$%d,0x%x",getrs(op),getrt(op),gettrapcode(op));
}
static void decode_tgeu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tgeu $%d,$%d,0x%x",getrs(op),getrt(op),gettrapcode(op));
}
static void decode_tlt(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tlt $%d,$%d,0x%x",getrs(op),getrt(op),gettrapcode(op));
}
static void decode_tltu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tltu $%d,$%d,0x%x",getrs(op),getrt(op),gettrapcode(op));
}
static void decode_teq(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"teq $%d,$%d,0x%x",getrs(op),getrt(op),gettrapcode(op));
}
static void decode_tne(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tne $%d,$%d,0x%x",getrs(op),getrt(op),gettrapcode(op));
}
static void decode_madd(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x70000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"madd $%d,$%d",getrs(op),getrt(op));
}
static void decode_maddu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x70000001)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"maddu $%d,$%d",getrs(op),getrt(op));
}
static void decode_mul(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x70000002)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mul $%d,$%d,$%d",getrd(op),getrs(op),getrt(op));
}
static void decode_msub(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x70000004)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"msub $%d,$%d",getrs(op),getrt(op));
}
static void decode_msubu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc00ffff, 0x70000005)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"msubu $%d,$%d",getrs(op),getrt(op));
}
static void decode_clz(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x70000020)&&check_cl(getrt(op), getrd(op))))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"clz $%d,$%d",getrd(op),getrs(op));
}
static void decode_clo(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xfc0007ff, 0x70000021)&&check_cl(getrt(op), getrd(op))))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"clo $%d,$%d",getrd(op),getrs(op));
}
static void decode_sdbbp(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"sdbbp 0x%x",getsyscode(op));
}
static void decode_bltz(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bltz $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bgez(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bgez $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bltzl(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bltzl $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bgezl(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bgezl $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_tgei(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tgei $%d,%d",getrs(op),getsimm(op));
}
static void decode_tgeiu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tgeiu $%d,%d",getrs(op),getsimm(op));
}
static void decode_tlti(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tlti $%d,%d",getrs(op),getsimm(op));
}
static void decode_tltiu(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tltiu $%d,%d",getrs(op),getsimm(op));
}
static void decode_teqi(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"teqi $%d,%d",getrs(op),getsimm(op));
}
static void decode_tnei(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"tnei $%d,%d",getrs(op),getsimm(op));
}
static void decode_bltzal(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bltzal $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bgezal(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bgezal $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bltzall(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bltzall $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_bgezall(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"bgezall $%d,0x%x",getrs(op),getbroff(pc,op));
}
static void decode_mfc0(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffe007f8, 0x40000000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mfc0 $%d,$%d,%d",getrt(op),getrd(op),getsel(op));
}
static void decode_mtc0(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffe007f8, 0x40800000)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"mtc0 $%d,$%d,%d",getrt(op),getrd(op),getsel(op));
}
static void decode_tlbr(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffffffff, 0x42000001)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"tlbr");
}
static void decode_tlbwi(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffffffff, 0x42000002)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"tlbwi");
}
static void decode_tlbwr(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffffffff, 0x42000006)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"tlbwr");
}
static void decode_tlbp(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffffffff, 0x42000008)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"tlbp");
}
static void decode_eret(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffffffff, 0x42000018)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"eret");
}
static void decode_deret(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
if (!(check_opcode(op, 0xffffffff, 0x4200001f)))
{
decode_illegal(outbuf, n, pc, op);
return;
}
snprintf(outbuf,n,"deret");
}
static void decode_wait(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
snprintf(outbuf,n,"wait 0x%x",getwaitcode(op));
}
static void decode_OPCODE(char *outbuf, size_t n, uint32_t pc, uint32_t op);
static void decode_SPC1(char *outbuf, size_t n, uint32_t pc, uint32_t op);
static void decode_SPC2(char *outbuf, size_t n, uint32_t pc, uint32_t op);
static void decode_R(char *outbuf, size_t n, uint32_t pc, uint32_t op);
static void decode_COP0(char *outbuf, size_t n, uint32_t pc, uint32_t op);
static void decode_CO(char *outbuf, size_t n, uint32_t pc, uint32_t op);
static void decode_OPCODE(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
switch (getopcode(op))
{
case 0:
decode_SPC1(outbuf, n, pc, op);
break;
case 1:
decode_R(outbuf, n, pc, op);
break;
case 2:
decode_j(outbuf, n, pc, op);
break;
case 3:
decode_jal(outbuf, n, pc, op);
break;
case 4:
decode_beq(outbuf, n, pc, op);
break;
case 5:
decode_bne(outbuf, n, pc, op);
break;
case 6:
decode_blez(outbuf, n, pc, op);
break;
case 7:
decode_bgtz(outbuf, n, pc, op);
break;
case 8:
decode_addi(outbuf, n, pc, op);
break;
case 9:
decode_addiu(outbuf, n, pc, op);
break;
case 10:
decode_slti(outbuf, n, pc, op);
break;
case 11:
decode_sltiu(outbuf, n, pc, op);
break;
case 12:
decode_andi(outbuf, n, pc, op);
break;
case 13:
decode_ori(outbuf, n, pc, op);
break;
case 14:
decode_xori(outbuf, n, pc, op);
break;
case 15:
decode_lui(outbuf, n, pc, op);
break;
case 16:
decode_COP0(outbuf, n, 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:
decode_unusable(outbuf, n, pc, op);
break;
case 20:
decode_beql(outbuf, n, pc, op);
break;
case 21:
decode_bnel(outbuf, n, pc, op);
break;
case 22:
decode_blezl(outbuf, n, pc, op);
break;
case 23:
decode_bgtzl(outbuf, n, 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:
decode_reserved(outbuf, n, pc, op);
break;
case 28:
decode_SPC2(outbuf, n, pc, op);
break;
case 32:
decode_lb(outbuf, n, pc, op);
break;
case 33:
decode_lh(outbuf, n, pc, op);
break;
case 34:
decode_lwl(outbuf, n, pc, op);
break;
case 35:
decode_lw(outbuf, n, pc, op);
break;
case 36:
decode_lbu(outbuf, n, pc, op);
break;
case 37:
decode_lhu(outbuf, n, pc, op);
break;
case 38:
decode_lwr(outbuf, n, pc, op);
break;
case 40:
decode_sb(outbuf, n, pc, op);
break;
case 41:
decode_sh(outbuf, n, pc, op);
break;
case 42:
decode_swl(outbuf, n, pc, op);
break;
case 43:
decode_sw(outbuf, n, pc, op);
break;
case 46:
decode_swr(outbuf, n, pc, op);
break;
case 47:
decode_cache(outbuf, n, pc, op);
break;
case 48:
decode_ll(outbuf, n, pc, op);
break;
case 51:
decode_pref(outbuf, n, pc, op);
break;
case 56:
decode_sc(outbuf, n, pc, op);
break;
default:
/* unreachable */
abort();
}
}
static void decode_SPC1(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
switch (getfunction(op))
{
case 0:
decode_sll(outbuf, n, pc, op);
break;
case 1:
decode_unusable(outbuf, n, pc, op);
break;
case 2:
decode_srl(outbuf, n, pc, op);
break;
case 3:
decode_sra(outbuf, n, pc, op);
break;
case 4:
decode_sllv(outbuf, n, 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:
decode_reserved(outbuf, n, pc, op);
break;
case 6:
decode_srlv(outbuf, n, pc, op);
break;
case 7:
decode_srav(outbuf, n, pc, op);
break;
case 8:
decode_jr(outbuf, n, pc, op);
break;
case 9:
decode_jalr(outbuf, n, pc, op);
break;
case 10:
decode_movz(outbuf, n, pc, op);
break;
case 11:
decode_movn(outbuf, n, pc, op);
break;
case 12:
decode_syscall(outbuf, n, pc, op);
break;
case 13:
decode_break(outbuf, n, pc, op);
break;
case 15:
decode_sync(outbuf, n, pc, op);
break;
case 16:
decode_mfhi(outbuf, n, pc, op);
break;
case 17:
decode_mthi(outbuf, n, pc, op);
break;
case 18:
decode_mflo(outbuf, n, pc, op);
break;
case 19:
decode_mtlo(outbuf, n, pc, op);
break;
case 24:
decode_mult(outbuf, n, pc, op);
break;
case 25:
decode_multu(outbuf, n, pc, op);
break;
case 26:
decode_div(outbuf, n, pc, op);
break;
case 27:
decode_divu(outbuf, n, pc, op);
break;
case 32:
decode_add(outbuf, n, pc, op);
break;
case 33:
decode_addu(outbuf, n, pc, op);
break;
case 34:
decode_sub(outbuf, n, pc, op);
break;
case 35:
decode_subu(outbuf, n, pc, op);
break;
case 36:
decode_and(outbuf, n, pc, op);
break;
case 37:
decode_or(outbuf, n, pc, op);
break;
case 38:
decode_xor(outbuf, n, pc, op);
break;
case 39:
decode_nor(outbuf, n, pc, op);
break;
case 42:
decode_slt(outbuf, n, pc, op);
break;
case 43:
decode_sltu(outbuf, n, pc, op);
break;
case 48:
decode_tge(outbuf, n, pc, op);
break;
case 49:
decode_tgeu(outbuf, n, pc, op);
break;
case 50:
decode_tlt(outbuf, n, pc, op);
break;
case 51:
decode_tltu(outbuf, n, pc, op);
break;
case 52:
decode_teq(outbuf, n, pc, op);
break;
case 54:
decode_tne(outbuf, n, pc, op);
break;
default:
/* unreachable */
abort();
}
}
static void decode_SPC2(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
switch (getfunction(op))
{
case 0:
decode_madd(outbuf, n, pc, op);
break;
case 1:
decode_maddu(outbuf, n, pc, op);
break;
case 2:
decode_mul(outbuf, n, 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:
decode_reserved(outbuf, n, pc, op);
break;
case 4:
decode_msub(outbuf, n, pc, op);
break;
case 5:
decode_msubu(outbuf, n, pc, op);
break;
case 32:
decode_clz(outbuf, n, pc, op);
break;
case 33:
decode_clo(outbuf, n, pc, op);
break;
case 63:
decode_sdbbp(outbuf, n, pc, op);
break;
default:
/* unreachable */
abort();
}
}
static void decode_R(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
switch (getrt(op))
{
case 0:
decode_bltz(outbuf, n, pc, op);
break;
case 1:
decode_bgez(outbuf, n, pc, op);
break;
case 2:
decode_bltzl(outbuf, n, pc, op);
break;
case 3:
decode_bgezl(outbuf, n, 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:
decode_reserved(outbuf, n, pc, op);
break;
case 8:
decode_tgei(outbuf, n, pc, op);
break;
case 9:
decode_tgeiu(outbuf, n, pc, op);
break;
case 10:
decode_tlti(outbuf, n, pc, op);
break;
case 11:
decode_tltiu(outbuf, n, pc, op);
break;
case 12:
decode_teqi(outbuf, n, pc, op);
break;
case 14:
decode_tnei(outbuf, n, pc, op);
break;
case 16:
decode_bltzal(outbuf, n, pc, op);
break;
case 17:
decode_bgezal(outbuf, n, pc, op);
break;
case 18:
decode_bltzall(outbuf, n, pc, op);
break;
case 19:
decode_bgezall(outbuf, n, pc, op);
break;
default:
/* unreachable */
abort();
}
}
static void decode_COP0(char *outbuf, size_t n, uint32_t pc, uint32_t op)
{
switch (getrs(op))
{
case 0:
decode_mfc0(outbuf, n, 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:
decode_reserved(outbuf, n, pc, op);
break;
case 4:
decode_mtc0(outbuf, n, 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:
decode_CO(outbuf, n, pc, op);
break;
default:
/* unreachable */
abort();
}
}
static void decode_CO(char *outbuf, size_t n, uint32_t pc, uint32_t 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:
decode_reserved(outbuf, n, pc, op);
break;
case 1:
decode_tlbr(outbuf, n, pc, op);
break;
case 2:
decode_tlbwi(outbuf, n, pc, op);
break;
case 6:
decode_tlbwr(outbuf, n, pc, op);
break;
case 8:
decode_tlbp(outbuf, n, pc, op);
break;
case 24:
decode_eret(outbuf, n, pc, op);
break;
case 31:
decode_deret(outbuf, n, pc, op);
break;
case 32:
decode_wait(outbuf, n, pc, op);
break;
default:
/* unreachable */
abort();
}
}