/************************************************************* * File: mon/machine.c * Purpose: Part of core Monitor * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970304 Start of revision history * 980717 Added jalx to is_jal, and other functions. * 980823 Added mtd, mfd, RS_CN * 980904 Removed addciu. Conflict w SDBBP and what is it anyway? * 980904 Added SDBBP and DERET * 981026 Added eret. */ #include #include #include /* * The disassembler in this module is used by pmon/dis.c, tools/rdsrec.c, * tools/rdfrec.c, and msim/dis.c. */ #define FS_(x) (((x) >> 11) & ((1L << 5) - 1)) #define FT_(x) (((x) >> 16) & ((1L << 5) - 1)) #define FD_(x) (((x) >> 6) & ((1L << 5) - 1)) #define RS_(x) (((x) >> 21) & ((1L << 5) - 1)) #define RT_(x) (((x) >> 16) & ((1L << 5) - 1)) #define RD_(x) (((x) >> 11) & ((1L << 5) - 1)) #define IMM_(x) (((x) >> 0) & ((1L << 16) - 1)) #define TARGET_(x) (((x) >> 0) & ((1L << 26) - 1)) #define SHAMT_(x) (((x) >> 6) & ((1L << 5) - 1)) #define RX_(x) (((x) >> 8) & ((1L << 3) - 1)) #define RY_(x) (((x) >> 5) & ((1L << 3) - 1)) #ifndef NOANSI #define UIMMX_(x) ( \ (((x)&(((1<<5)-1)<<16)) >> 16-11) || \ (((x)&(((1<<6)-1)<<21)) >> 21-4) || \ (((x)&(((1<<5)-1)<<0) >> 0)) ) #endif #define comma() strcat(dest,",") #define rd() strcat(dest,regnames[(int)RD_(inst)]) #define rs() strcat(dest,regnames[(int)RS_(inst)]) #define rt() strcat(dest,regnames[(int)RT_(inst)]) #define fd() strcat(dest,c1dRegNames[(int)FD_(inst)]) #define fs() strcat(dest,c1dRegNames[(int)FS_(inst)]) #define ft() strcat(dest,c1dRegNames[(int)FT_(inst)]) #define c0() strcat(dest,c0regNames[(int)RD_(inst)]) #define c1() strcat(dest,c1dRegNames[(int)RD_(inst)]) #define c2() strcat(dest,c2dRegNames[(int)RD_(inst)]) #define cn() strcat(dest,regs_hw[(int)RD_(inst)]) #define c0ft() strcat(dest,c0regNames[(int)RT_(inst)]) #define c1ft() strcat(dest,c1dRegNames[(int)RT_(inst)]) #define cnft() strcat(dest,regs_hw[(int)RT_(inst)]) #define cc1() strcat(dest,regs_hw[(int)RD_(inst)]) #define cc2() strcat(dest,c2cRegNames[(int)RD_(inst)]) typedef enum { RD_RS_RT, RT_RS_IMM, OFFSET, RS_RT_OFF, RS_OFF, NOOPR, RT_RD, COFUN, RS_RT, TARGET, JALR, RSX, RD_RT_SFT, LOAD_STORE, RT_IMM, RDX, RD_RT_RS, RT_RS_SIMM, RT_SIMM, JR, RT_C0, RT_C1, RT_CN, RT_CC1, LDSTC0, LDSTC1, LDSTCN, WRD, FT_FS_FD, FS_FD, FT_FS, RT_C2, RT_CC2, BPCODE, RS_SIMM, CACHE_OP, RD_RS, OFF_BASE, JALX_TARG, JAL_TARG, RS_CN, DBPCODE } TYPE; typedef struct DISTBL { char *str; Ulong mask, code; TYPE type; } DISTBL; /* software register names */ char *regs_sw[] = { "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" }; /* hardware register names */ char *regs_hw[] = { "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" }; char *c1reg[] = { "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" }; char *c0reg[] = { "C0_INDEX", "C0_RANDOM", "C0_ENTRYLO", "$3", "C0_CONTEXT", "$5", "$6", "$7", "C0_BADVA", "$9", "C0_ENTRYHI", "$11", "C0_SR", "C0_CAUSE", "C0_EPC", "C0_PRID", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" }; DISTBL distbl[] = { { "sll", 0xffe0003fL, 0x00000000L, RD_RT_SFT }, { "selsr", 0xfc0007ffL, 0x00000001L, RD_RS_RT }, { "srl", 0xffe0003fL, 0x00000002L, RD_RT_SFT }, { "sra", 0xffe0003fL, 0x00000003L, RD_RT_SFT }, { "sllv", 0xfc0007ffL, 0x00000004L, RD_RT_RS }, { "selsl", 0xfc0007ffL, 0x00000005L, RD_RS_RT }, { "srlv", 0xfc0007ffL, 0x00000006L, RD_RT_RS }, { "srav", 0xfc0007ffL, 0x00000007L, RD_RT_RS }, { "jr", 0xfc1fffffL, 0x00000008L, JR }, { "jalr", 0xfc1f07ffL, 0x00000009L, JALR }, { "ffs", 0xfc1f07ffL, 0x0000000aL, RD_RS }, { "ffc", 0xfc1f07ffL, 0x0000000bL, RD_RS }, { "syscall", 0xffffffffL, 0x0000000cL, NOOPR }, { "break", 0xfc00003fL, 0x0000000dL, BPCODE }, { "mfhi", 0xffff07ffL, 0x00000010L, RDX }, { "mthi", 0xfc1fffffL, 0x00000011L, RSX }, { "mflo", 0xffff07ffL, 0x00000012L, RDX }, { "mtlo", 0xfc1fffffL, 0x00000013L, RSX }, { "mult", 0xfc00ffffL, 0x00000018L, RS_RT }, { "multu", 0xfc00ffffL, 0x00000019L, RS_RT }, { "div", 0xfc00ffffL, 0x0000001aL, RS_RT }, { "divu", 0xfc00ffffL, 0x0000001bL, RS_RT }, { "madd", 0xfc00ffffL, 0x0000001cL, RS_RT }, { "maddu", 0xfc00ffffL, 0x0000001dL, RS_RT }, { "msub", 0xfc00ffffL, 0x0000001eL, RS_RT }, { "msubu", 0xfc00ffffL, 0x0000001fL, RS_RT }, { "add", 0xfc0007ffL, 0x00000020L, RD_RS_RT }, { "addu", 0xfc0007ffL, 0x00000021L, RD_RS_RT }, { "sub", 0xfc0007ffL, 0x00000022L, RD_RS_RT }, { "subu", 0xfc0007ffL, 0x00000023L, RD_RS_RT }, { "and", 0xfc0007ffL, 0x00000024L, RD_RS_RT }, { "or", 0xfc0007ffL, 0x00000025L, RD_RS_RT }, { "xor", 0xfc0007ffL, 0x00000026L, RD_RS_RT }, { "nor", 0xfc0007ffL, 0x00000027L, RD_RS_RT }, { "min", 0xfc0007ffL, 0x00000028L, RD_RS_RT }, { "max", 0xfc0007ffL, 0x00000029L, RD_RS_RT }, { "slt", 0xfc0007ffL, 0x0000002aL, RD_RS_RT }, { "sltu", 0xfc0007ffL, 0x0000002bL, RD_RS_RT }, { "tge", 0xfc00003fL, 0x00000030L, RS_RT }, { "tgeu", 0xfc00003fL, 0x00000031L, RS_RT }, { "tlt", 0xfc00003fL, 0x00000032L, RS_RT }, { "tltu", 0xfc00003fL, 0x00000033L, RS_RT }, { "teq", 0xfc00003fL, 0x00000034L, RS_RT }, { "tne", 0xfc00003fL, 0x00000036L, RS_RT }, { "dsll", 0xffe0003fL, 0x00000038L, RD_RT_SFT }, { "bltz", 0xfc1f0000L, 0x04000000L, RS_OFF }, { "bgez", 0xfc1f0000L, 0x04010000L, RS_OFF }, { "bltzl", 0xfc1f0000L, 0x04020000L, RS_OFF }, { "bgezl", 0xfc1f0000L, 0x04030000L, RS_OFF }, { "tgei", 0xfc1f0000L, 0x04080000L, RS_SIMM }, { "tgeiu", 0xfc1f0000L, 0x04090000L, RS_SIMM }, { "tlti", 0xfc1f0000L, 0x040a0000L, RS_SIMM }, { "tltiu", 0xfc1f0000L, 0x040b0000L, RS_SIMM }, { "teqi", 0xfc1f0000L, 0x040c0000L, RS_SIMM }, { "tnei", 0xfc1f0000L, 0x040e0000L, RS_SIMM }, { "bltzal", 0xfc1f0000L, 0x04100000L, RS_OFF }, { "bgezal", 0xfc1f0000L, 0x04110000L, RS_OFF }, { "bltzall", 0xfc1f0000L, 0x04120000L, RS_OFF }, { "bgezall", 0xfc1f0000L, 0x04130000L, RS_OFF }, { "j", 0xfc000000L, 0x08000000L, TARGET }, { "jal", 0xfc000000L, 0x0c000000L, JAL_TARG }, { "beq", 0xfc000000L, 0x10000000L, RS_RT_OFF }, { "bne", 0xfc000000L, 0x14000000L, RS_RT_OFF }, { "blez", 0xfc1f0000L, 0x18000000L, RS_OFF }, { "bgtz", 0xfc1f0000L, 0x1c000000L, RS_OFF }, { "addi", 0xfc000000L, 0x20000000L, RT_RS_SIMM }, { "addiu", 0xfc000000L, 0x24000000L, RT_RS_SIMM }, { "slti", 0xfc000000L, 0x28000000L, RT_RS_SIMM }, { "sltiu", 0xfc000000L, 0x2c000000L, RT_RS_SIMM }, { "andi", 0xfc000000L, 0x30000000L, RT_RS_IMM }, { "ori", 0xfc000000L, 0x34000000L, RT_RS_IMM }, { "xori", 0xfc000000L, 0x38000000L, RT_RS_IMM }, { "lui", 0xfc000000L, 0x3c000000L, RT_IMM }, { "mfc0", 0xffe007ffL, 0x40000000L, RT_C0 }, { "ctc0", 0xffe007ffL, 0x40c00000L, RT_RD }, { "cfc0", 0xffe007ffL, 0x40400000L, RT_RD }, { "mtc0", 0xffe007ffL, 0x40800000L, RT_C0 }, { "bc0f", 0xffff0000L, 0x41000000L, OFFSET }, { "bc0t", 0xffff0000L, 0x41010000L, OFFSET }, { "bc0fl", 0xffff0000L, 0x41020000L, OFFSET }, { "bc0tl", 0xffff0000L, 0x41030000L, OFFSET }, { "tlbp", 0xffffffffL, 0x42000008L, NOOPR }, { "tlbr", 0xffffffffL, 0x42000001L, NOOPR }, { "tlbwi", 0xffffffffL, 0x42000002L, NOOPR }, { "tlbwr", 0xffffffffL, 0x42000006L, NOOPR }, { "rfe", 0xffffffffL, 0x42000010L, NOOPR }, { "eret", 0xffffffffL, 0x42000018L, NOOPR }, { "deret", 0xffffffffL, 0x4200001fL, NOOPR }, { "waiti", 0xffffffffL, 0x42000020L, NOOPR }, { "cop0", 0xfe000000L, 0x42000000L, COFUN }, { "mfc1", 0xffe007ffL, 0x44000000L, RT_C1 }, { "cfc1", 0xffe007ffL, 0x44400000L, RT_CC1 }, { "mtc1", 0xffe007ffL, 0x44800000L, RT_C1 }, { "ctc1", 0xffe007ffL, 0x44c00000L, RT_CC1 }, { "bc1f", 0xffff0000L, 0x45000000L, OFFSET }, { "bc1t", 0xffff0000L, 0x45010000L, OFFSET }, { "bc1fl", 0xffff0000L, 0x45020000L, OFFSET }, { "bc1tl", 0xffff0000L, 0x45030000L, OFFSET }, { "add.s", 0xfee0003fL, 0x46000000L, FT_FS_FD }, { "add.d", 0xfee0003fL, 0x46200000L, FT_FS_FD }, { "sub.s", 0xfee0003fL, 0x46000001L, FT_FS_FD }, { "sub.d", 0xfee0003fL, 0x46200001L, FT_FS_FD }, { "mul.s", 0xfee0003fL, 0x46000002L, FT_FS_FD }, { "mul.d", 0xfee0003fL, 0x46200002L, FT_FS_FD }, { "div.s", 0xfee0003fL, 0x46000003L, FT_FS_FD }, { "div.d", 0xfee0003fL, 0x46200003L, FT_FS_FD }, { "abs.s", 0xfee0003fL, 0x46000005L, FS_FD }, { "abs.d", 0xfee0003fL, 0x46200005L, FS_FD }, { "mov.s", 0xfee0003fL, 0x46000006L, FS_FD }, { "mov.d", 0xfee0003fL, 0x46200006L, FS_FD }, { "neg.s", 0xfee0003fL, 0x46000007L, FS_FD }, { "neg.d", 0xfee0003fL, 0x46200007L, FS_FD }, { "cvt.s.w", 0xfee0003fL, 0x46800020L, FS_FD }, { "cvt.s.d", 0xfee0003fL, 0x46200020L, FS_FD }, { "cvt.d.s", 0xfee0003fL, 0x46000021L, FS_FD }, { "cvt.d.w", 0xfee0003fL, 0x46800021L, FS_FD }, { "cvt.w.d", 0xfee0003fL, 0x46200024L, FS_FD }, { "cvt.w.s", 0xfee0003fL, 0x46000024L, FS_FD }, { "c.f.s", 0xfee0003fL, 0x46000030L, FT_FS }, { "c.f.d", 0xfee0003fL, 0x46200030L, FT_FS }, { "c.un.s", 0xfee0003fL, 0x46000031L, FT_FS }, { "c.un.d", 0xfee0003fL, 0x46200031L, FT_FS }, { "c.eq.s", 0xfee0003fL, 0x46000032L, FT_FS }, { "c.eq.d", 0xfee0003fL, 0x46200032L, FT_FS }, { "c.ueq.s", 0xfee0003fL, 0x46000033L, FT_FS }, { "c.ueq.d", 0xfee0003fL, 0x46200033L, FT_FS }, { "c.olt.s", 0xfee0003fL, 0x46000034L, FT_FS }, { "c.olt.d", 0xfee0003fL, 0x46200034L, FT_FS }, { "c.ult.s", 0xfee0003fL, 0x46000035L, FT_FS }, { "c.ult.d", 0xfee0003fL, 0x46200035L, FT_FS }, { "c.ole.s", 0xfee0003fL, 0x46000036L, FT_FS }, { "c.ole.d", 0xfee0003fL, 0x46200036L, FT_FS }, { "c.ule.s", 0xfee0003fL, 0x46000037L, FT_FS }, { "c.ule.d", 0xfee0003fL, 0x46200037L, FT_FS }, { "c.sf.s", 0xfee0003fL, 0x46000038L, FT_FS }, { "c.sf.d", 0xfee0003fL, 0x46200038L, FT_FS }, { "c.ngle.d", 0xfee0003fL, 0x46200039L, FT_FS }, { "c.ngle.s", 0xfee0003fL, 0x46000039L, FT_FS }, { "c.seq.s", 0xfee0003fL, 0x4600003aL, FT_FS }, { "c.lt.s", 0xfee0003fL, 0x4600003cL, FT_FS }, { "c.ngl.s", 0xfee0003fL, 0x4600003bL, FT_FS }, { "c.nge.s", 0xfee0003fL, 0x4600003dL, FT_FS }, { "c.le.s", 0xfee0003fL, 0x4600003eL, FT_FS }, { "c.ngt.s", 0xfee0003fL, 0x4600003fL, FT_FS }, { "c.seq.d", 0xfee0003fL, 0x4620003aL, FT_FS }, { "c.ngl.d", 0xfee0003fL, 0x4620003bL, FT_FS }, { "c.lt.d", 0xfee0003fL, 0x4620003cL, FT_FS }, { "c.nge.d", 0xfee0003fL, 0x4620003dL, FT_FS }, { "c.le.d", 0xfee0003fL, 0x4620003eL, FT_FS }, { "c.ngt.d", 0xfee0003fL, 0x4620003fL, FT_FS }, { "cop1", 0xfe000000L, 0x46000000L, COFUN }, #ifdef LR33000 { "mfc2", 0xffe007ffL, 0x48000000L, RT_C2 }, { "cfc2", 0xffe007ffL, 0x48400000L, RT_CC2 }, { "mtc2", 0xffe007ffL, 0x48800000L, RT_C2 }, { "ctc2", 0xffe007ffL, 0x48c00000L, RT_CC2 }, #else { "mfc2", 0xffe007ffL, 0x48000000L, RT_CN }, { "cfc2", 0xffe007ffL, 0x48400000L, RT_CN }, { "mtc2", 0xffe007ffL, 0x48800000L, RT_CN }, { "ctc2", 0xffe007ffL, 0x48c00000L, RT_CN }, #endif { "bc2f", 0xffff0000L, 0x49000000L, OFFSET }, { "bc2t", 0xffff0000L, 0x49010000L, OFFSET }, { "bc2fl", 0xffff0000L, 0x49020000L, OFFSET }, { "bc2tl", 0xffff0000L, 0x49030000L, OFFSET }, #ifdef LR33020 { "sstep", 0xfeffffffL, 0x4a00ffffL, NOOPR }, { "sbstep", 0xfeffffffL, 0x4a40ffffL, NOOPR }, { "wstep", 0xfeffffffL, 0x4a80ffffL, NOOPR }, { "wstep_l", 0xfeffffffL, 0x4a88ffffL, NOOPR }, { "wstep_r", 0xfeffffffL, 0x4a84ffffL, NOOPR }, { "wstep_l_r", 0xfeffffffL, 0x4a8cffffL, NOOPR }, { "wstep_s", 0xfeffffffL, 0x4aa0ffffL, NOOPR }, { "wstep_s_l", 0xfeffffffL, 0x4aa8ffffL, NOOPR }, { "wstep_s_r", 0xfeffffffL, 0x4aa4ffffL, NOOPR }, { "wstep_s_l_r",0xfeffffffL, 0x4aacffffL, NOOPR }, { "wstep_sb", 0xfeffffffL, 0x4ab0ffffL, NOOPR }, { "wstep_sb_l", 0xfeffffffL, 0x4ab8ffffL, NOOPR }, { "wstep_sb_r", 0xfeffffffL, 0x4ab4ffffL, NOOPR }, { "wstep_sb_l_r",0xfeffffffL, 0x4abcffffL, NOOPR }, { "wstep_four", 0xfeffffffL, 0x4a82ffffL, NOOPR }, { "wstep_bfour",0xfeffffffL, 0x4a81ffffL, NOOPR }, { "bstep_bfour",0xfeffffffL, 0x4ac1ffffL, NOOPR }, { "bstep", 0xfeffffffL, 0x4ac0ffffL, NOOPR }, { "bstep_l", 0xfeffffffL, 0x4ac8ffffL, NOOPR }, { "bstep_r", 0xfeffffffL, 0x4ac4ffffL, NOOPR }, { "bstep_l_r", 0xfeffffffL, 0x4accffffL, NOOPR }, { "bstep_s", 0xfeffffffL, 0x4ae0ffffL, NOOPR }, { "bstep_s_l", 0xfeffffffL, 0x4ae8ffffL, NOOPR }, { "bstep_s_r", 0xfeffffffL, 0x4ae4ffffL, NOOPR }, { "bstep_s_l_r",0xfeffffffL, 0x4aecffffL, NOOPR }, { "bstep_sb", 0xfeffffffL, 0x4af0ffffL, NOOPR }, { "bstep_sb_l", 0xfeffffffL, 0x4af8ffffL, NOOPR }, { "bstep_sb_r", 0xfeffffffL, 0x4af4ffffL, NOOPR }, { "bstep_sb_l_r",0xfeffffffL, 0x4afcffffL, NOOPR }, { "wstep_i", 0xfeffffffL, 0x4a807fffL, NOOPR }, { "wstep_l_i", 0xfeffffffL, 0x4a887fffL, NOOPR }, { "wstep_r_i", 0xfeffffffL, 0x4a847fffL, NOOPR }, { "wstep_l_r_i",0xfeffffffL, 0x4a8c7fffL, NOOPR }, { "wstep_s_i", 0xfeffffffL, 0x4aa07fffL, NOOPR }, { "wstep_s_l_i",0xfeffffffL, 0x4aa87fffL, NOOPR }, { "wstep_s_r_i",0xfeffffffL, 0x4aa47fffL, NOOPR }, { "wstep_s_l_r_i",0xfeffffffL, 0x4aac7fffL, NOOPR }, { "wstep_sb_i", 0xfeffffffL, 0x4ab07fffL, NOOPR }, { "wstep_sb_l_i",0xfeffffffL, 0x4ab87fffL, NOOPR }, { "wstep_sb_r_i",0xfeffffffL, 0x4ab47fffL, NOOPR }, { "wstep_sb_l_r_i",0xfeffffffL, 0x4abc7fffL, NOOPR }, { "wstep_four_i",0xfeffffffL, 0x4a827fffL, NOOPR }, { "wstep_bfour_i",0xfeffffffL, 0x4a817fffL, NOOPR }, { "bstep_bfour_i",0xfeffffffL, 0x4ac17fffL, NOOPR }, { "bstep_i", 0xfeffffffL, 0x4ac07fffL, NOOPR }, { "bstep_l_i", 0xfeffffffL, 0x4ac87fffL, NOOPR }, { "bstep_r_i", 0xfeffffffL, 0x4ac47fffL, NOOPR }, { "bstep_l_r_i",0xfeffffffL, 0x4acc7fffL, NOOPR }, { "bstep_s_i", 0xfeffffffL, 0x4ae07fffL, NOOPR }, { "bstep_s_l_i",0xfeffffffL, 0x4ae87fffL, NOOPR }, { "bstep_s_r_i",0xfeffffffL, 0x4ae47fffL, NOOPR }, { "bstep_s_l_r_i",0xfeffffffL, 0x4aec7fffL, NOOPR }, #else { "cop2", 0xfe000000L, 0x4a000000L, COFUN }, #endif /* LR33020 */ { "mfc3", 0xffe007ffL, 0x4c000000L, RT_CN }, { "mtc3", 0xffe007ffL, 0x4c800000L, RT_CN }, { "ctc3", 0xffe007ffL, 0x4cc00000L, RT_CN }, { "cfc3", 0xffe007ffL, 0x4c400000L, RT_CN }, { "bc3f", 0xffff0000L, 0x4d000000L, OFFSET }, { "bc3t", 0xffff0000L, 0x4d010000L, OFFSET }, { "bc3fl", 0xffff0000L, 0x4d020000L, OFFSET }, { "bc3tl", 0xffff0000L, 0x4d030000L, OFFSET }, { "cop3", 0xfe000000L, 0x4e000000L, COFUN }, { "beql", 0xfc000000L, 0x50000000L, RS_RT_OFF }, { "bnel", 0xfc000000L, 0x54000000L, RS_RT_OFF }, { "blezl", 0xfc1f0000L, 0x58000000L, RS_OFF }, { "bgtzl", 0xfc1f0000L, 0x5c000000L, RS_OFF }, { "sdbbp", 0xfc00003fL, 0x7000003fL, DBPCODE }, { "jalx", 0xfc000000L, 0x74000000L, JALX_TARG }, { "mtd", 0xfc1f07ffL, 0x78000000L, RS_CN }, { "mfd", 0xffe007ffL, 0x7c000000L, RT_CN }, { "lb", 0xfc000000L, 0x80000000L, LOAD_STORE }, { "lh", 0xfc000000L, 0x84000000L, LOAD_STORE }, { "lwl", 0xfc000000L, 0x88000000L, LOAD_STORE }, { "lw", 0xfc000000L, 0x8c000000L, LOAD_STORE }, { "lbu", 0xfc000000L, 0x90000000L, LOAD_STORE }, { "lhu", 0xfc000000L, 0x94000000L, LOAD_STORE }, { "lwr", 0xfc000000L, 0x98000000L, LOAD_STORE }, { "sb", 0xfc000000L, 0xa0000000L, LOAD_STORE }, { "sh", 0xfc000000L, 0xa4000000L, LOAD_STORE }, { "sw", 0xfc000000L, 0xac000000L, LOAD_STORE }, { "swl", 0xfc000000L, 0xa8000000L, LOAD_STORE }, { "swr", 0xfc000000L, 0xb8000000L, LOAD_STORE }, #if 0 /* non-compliant instructions used by 4010/11 */ { "flushi", 0xfc1f0000L, 0xbc010000L, NOOPR }, { "flushd", 0xfc1f0000L, 0xbc020000L, NOOPR }, { "flushid", 0xfc1f0000L, 0xbc030000L, NOOPR }, { "wb", 0xfc1f0000L, 0xbc040000L, OFF_BASE }, #endif { "cache", 0xfc000000L, 0xbc000000L, CACHE_OP }, { "lwc0", 0xfc000000L, 0xc0000000L, LDSTC0 }, { "lwc1", 0xfc000000L, 0xc4000000L, LDSTC1 }, { "lwc2", 0xfc000000L, 0xc8000000L, LDSTCN }, { "lwc3", 0xfc000000L, 0xcc000000L, LDSTCN }, { "ld", 0xfc000000L, 0xdc000000L, LOAD_STORE }, { "swc0", 0xfc000000L, 0xe0000000L, LDSTC0 }, { "swc1", 0xfc000000L, 0xe4000000L, LDSTC1 }, { "swc2", 0xfc000000L, 0xe8000000L, LDSTCN }, { "swc3", 0xfc000000L, 0xec000000L, LDSTCN }, { "sd", 0xfc000000L, 0xfc000000L, LOAD_STORE }, /* must be last !! never be move/removed */ { ".word", 0x00000000L, 0x00000000L, WRD } }; DISTBL *get_distbl(); long inst; char **regnames; char **c0regNames; char **c1dRegNames, **c1cRegNames; char **c2dRegNames, **c2cRegNames; char **c3dRegNames, **c3cRegNames; Ulong cpuType; #ifdef NOANSI static void imm(); static void simm(); #else static void imm(char *dest); static void simm(char *dest); #endif /************************************************************* * long disasm(dest,addr,bits) * disassemble instruction 'bits' */ ADDR disasm(char *dest,ADDR addr,Ulong bits) { DISTBL *pt; char tmp[40]; long v,v1,w; int i,sz; inst = bits; if (regnames==0) regnames = regs_sw; if (c0regNames==0) c0regNames = c0reg; if (c1dRegNames==0) c1dRegNames = c1reg; if (c1cRegNames==0) c1cRegNames = regs_hw; if (c2dRegNames==0) c2dRegNames = regs_hw; if (c2cRegNames==0) c2cRegNames = regs_hw; if (c3dRegNames==0) c3dRegNames = regs_hw; if (c3cRegNames==0) c3cRegNames = regs_hw; if(!adr2symoff(dest,addr,12)) sprintf(dest,"%08lx",addr&~1); if (addr&3) return dis16(dest,addr,bits); sprintf(tmp," %08lx ",inst); strcat(dest,tmp); sz = 4; if(inst == 0L){ strcat(dest,"nop"); return(addr + 4L); } pt = get_distbl(inst); i = strlen(pt->str); strcat(dest,pt->str); while(i++ < 8) strcat(dest," "); switch(pt->type) { case FT_FS_FD: fd(), comma(), fs(), comma(), ft(); break; case FS_FD: fd(), comma(), fs(); break; case FT_FS: fs(), comma(), ft(); break; case RT_RS_IMM: rt(), comma(), rs(), comma(),imm(dest); break; case RT_RS_SIMM:rt(), comma(), rs(),comma(),simm(dest); break; case RS_SIMM: rs(),comma(),simm(dest); break; case RT_IMM: rt(), comma(),imm(dest); break; case RT_SIMM: rt(), comma(), simm(dest); break; case RT_RD: rt(), comma(); case RDX: rd(); break; case RT_C0: rt(),comma(),c0(); break; case RT_C1: rt(),comma(),c1(); break; #ifdef LR33000 case RT_C2: rt(),comma(),c2(); break; case RT_CC2: rt(),comma(),cc2(); break; #endif case RT_CN: rt(),comma(),cn(); break; case RT_CC1: rt(),comma(),cc1(); break; case RD_RT_RS: rd(), comma(), rt(), comma(); case JR: case RSX: rs(); break; case RD_RS: rd(), comma(), rs(); break; case RS_CN: rs(), comma(), cn(); break; case RD_RS_RT: rd(), comma(); case RS_RT: rs(), comma(), rt(); break; case RD_RT_SFT: rd(), comma(), rt(), comma(); sprintf(tmp,"0x%x",SHAMT_(inst)); strcat(dest,tmp); mkcomment(dest,"# %d",SHAMT_(inst)); break; case RS_RT_OFF: case RS_OFF: rs(), comma(); if(pt->type == RS_RT_OFF) rt(), comma(); case OFFSET: v = IMM_(inst); if(v & (1L << 15)) v |= 0xffff0000L; v1 = addr + 4L + (v << 2); if (!adr2symoff(tmp,v1,0)) sprintf(tmp,"%x",v1); strcat(dest,tmp); mkcomment(dest,"# 0x%08lx",v1); break; case DBPCODE: sprintf(tmp,"%d",(inst>>6)&0xfffff); strcat(dest,tmp); break; case BPCODE: sprintf(tmp,"%d",(inst>>16)&0x3ff); strcat(dest,tmp); break; case COFUN: sprintf(tmp,"0x%x",inst & 0x01ffffffL); strcat(dest,tmp); break; case NOOPR: break; case JALX_TARG: v = (inst & 0x03ffffffL) << 2; v |= (addr & 0xf0000000L); if (!adr2symoff(tmp,v+1,0)) sprintf(tmp,"%x",v); strcat(dest,tmp); mkcomment(dest,"# 0x%08lx",v); break; case JAL_TARG: case TARGET: v = (inst & 0x03ffffffL) << 2; v |= (addr & 0xf0000000L); if (!adr2symoff(tmp,v,0)) sprintf(tmp,"%x",v); strcat(dest,tmp); mkcomment(dest,"# 0x%08lx",v); break; case JALR: if(RD_(inst) != 31L) rd(), comma(); rs(); break; case LDSTC0: v = IMM_(inst); if(v & (1L << 15)) v |= 0xffff0000L; c0ft(), comma(); sprintf(tmp,"%d(",v); strcat(dest,tmp); rs(); strcat(dest,")"); mkcomment(dest,"# 0x%x",v); break; case LDSTC1: v = IMM_(inst); if(v & (1L << 15)) v |= 0xffff0000L; c1ft(), comma(); sprintf(tmp,"%d(",v); strcat(dest,tmp); rs(); strcat(dest,")"); mkcomment(dest,"# 0x%x",v); break; case LDSTCN: v = IMM_(inst); if(v & (1L << 15)) v |= 0xffff0000L; cnft(), comma(); sprintf(tmp,"%d(",v); strcat(dest,tmp); rs(); strcat(dest,")"); mkcomment(dest,"# 0x%x",v); break; case CACHE_OP: v = IMM_(inst); if(v & (1L << 15)) v |= 0xffff0000L; sprintf(tmp,"%d,%d(",RT_(inst),v); strcat(dest,tmp); rs(); strcat(dest,")"); mkcomment(dest,"# 0x%x",v); break; case OFF_BASE: v = IMM_(inst); if(v & (1L << 15)) v |= 0xffff0000L; sprintf(tmp,"%d(",v); strcat(dest,tmp); rs(); strcat(dest,")"); mkcomment(dest,"# 0x%x",v); break; case LOAD_STORE: v = IMM_(inst); if(v & (1L << 15)) v |= 0xffff0000L; rt(), comma(); sprintf(tmp,"%d(",v); strcat(dest,tmp); rs(); strcat(dest,")"); mkcomment(dest,"# 0x%x",v); break; case WRD: sprintf(tmp,"%08lx",inst); strcat(dest,tmp); strcat(dest," # "); w = addr; for(i = 0; i < 4 ; i++){ v = read_target8(w++); if (isprint(v)) strccat(dest,(char)v); else strccat(dest,'.'); } break; } return(addr + sz); } /************************************************************* * DISTBL *get_distbl(bits) */ DISTBL *get_distbl(bits) long bits; { DISTBL *pt = distbl; while((bits & pt->mask) != pt->code) ++pt; return(pt); } /************************************************************* * int is_branch(addr,inst) */ int is_branch(ADDR addr,Ulong inst) { DISTBL *pt; if (addr&1) return mips16_is_branch(addr,inst); pt = get_distbl(inst); switch(pt->type){ case OFFSET: case RS_RT_OFF: case RS_OFF: case TARGET: case JAL_TARG: case JALX_TARG: case JALR: case JR: return(1); default: return(0); } } /************************************************************* * int is_branch_likely(inst) * returns true if instr at adr is a branch likely instr */ int is_branch_likely(Ulong inst) { DISTBL *pt; int len; pt = get_distbl(inst); if (pt->str[0] != 'b') return(0); len = strlen(pt->str); if (pt->str[len-1] == 'l' && pt->str[len-2] != 'a') return(1); return(0); } /************************************************************* * int is_conditional_branch(addr,inst) */ int is_conditional_branch(ADDR addr,Ulong inst) { DISTBL *pt; if (addr&1) return mips16_is_conditional_branch(addr,inst); pt = get_distbl(inst); switch(pt->type) { case OFFSET: /* branch on copN */ case RS_RT_OFF: case RS_OFF: return(1); default: return(0); } } /************************************************************* * is_jr(addr,inst) */ int is_jr(ADDR addr,Ulong inst) { DISTBL *pt; if (addr&1) return mips16_is_jr(addr,inst); pt = get_distbl(inst); if (pt->type == JR) return(1); return(0); } /************************************************************* * is_jal(addr,inst) */ int is_jal(ADDR addr,Ulong inst) { DISTBL *pt; if (addr&1) return mips16_is_jal(addr,inst); #if 0 op = getfield(inst,6,26); if (op == 3) return(1); if (op == 0 && getfield(inst,6,0) == 9) return(1); return(0); #else pt = get_distbl(inst); switch(pt->type) { case JALR: case JAL_TARG: case JALX_TARG: return(1); default: return(0); } #endif } /************************************************************* * ADDR branch_target_address(adr,inst) */ ADDR branch_target_address(ADDR adr,Ulong inst) { DISTBL *pt; Ulong val; pt = get_distbl(inst); switch(pt->type) { case OFFSET: case RS_RT_OFF: case RS_OFF: val = inst & 0xffff; if(val & 0x8000) val |= 0xffff0000; return(adr + 4 + (val << 2)); case JAL_TARG: case TARGET: val = inst & 0x3ffffff; return(((adr + 4) & 0xf0000000) | (val << 2)); case JALR: case JR: val = RS_(inst); return(getGpr(val).lo); case JALX_TARG: val = (inst & 0x03ffffffL) << 2; val |= (adr & 0xf0000000L); return(val+1); default: return(0); } } /************************************************************* * static void simm(char *dest) * signed immediate value */ static void simm(dest) char *dest; { char tmp[20]; long v; v = IMM_(inst); sprintf(tmp,"0x%x",v); strcat(dest,tmp); if (v >= 0 && v <= 9) return; if(v & (1L << 15)) v |= 0xffff0000L; mkcomment(dest,"# %d",v); } /************************************************************* * static void imm(char *dest) * unsigned immediate value */ static void imm(dest) char *dest; { char tmp[20]; long v; v = IMM_(inst); sprintf(tmp,"0x%x",v); strcat(dest,tmp); if (v >= 0 && v <= 9) return; mkcomment(dest,"# %d",v); } /************************************************************* * void mkcomment(char *p,char *fmt,Ulong v) * generate an appropriate comment */ void mkcomment(char *p,char *fmt,Ulong v) { char tmp[20]; int n; if (v >= 0 && v <= 9) return; for (n=60-strlen(p);n>0;n--) strcat(p," "); sprintf(tmp,fmt,v); strcat(p,tmp); } static do_bltz(x) {return((x<0)?1:0);} static do_bgez(x) {return((x>=0)?1:0);} static do_beq(x,y) {return((x==y)?1:0);} static do_bne(x,y) {return((x!=y)?1:0);} static do_blez(x) {return((x<=0)?1:0);} static do_bgtz(x) {return((x>0)?1:0);} static Func *bcc_table[] = {0,do_bltz,do_bgez,0,do_beq, do_bne, do_blez,do_bgtz}; /************************************************************* * ADDR actual_branch_target_address(adr,inst) */ ADDR actual_branch_target_address(ADDR adr,Ulong inst) { int s,t,v; Func *func; ADDR target; if (adr&1) return mips16_actual_branch_target_address(adr,inst); target = branch_target_address(adr,inst); if (!is_conditional_branch(adr,inst)) return(target); if (getfield(inst,3,26) == 1 && getfield(inst,1,16) == 1) v = 2; else v = getfield(inst,3,26); func = bcc_table[v]; if (!func) return(adr+8); /* error condition - should never happen */ s = getfield(inst,5,21); t = getfield(inst,5,16); if ((*func)(read_target(XT_GPR,s,0),read_target(XT_GPR,t,0))) return(target); else return(adr+8); } /************************************************************* */ int instr_size(ADDR adr,Ulong inst) { if ((adr&1)==0) return(4); if (mips16_is_extended(inst)) return(4); return(2); }