diff --git a/librz/arch/isa/mips/mips_assembler.h b/librz/arch/isa/mips/mips_assembler.h deleted file mode 100644 index 1436983c32d..00000000000 --- a/librz/arch/isa/mips/mips_assembler.h +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2012-2018 pancake -// SPDX-License-Identifier: LGPL-3.0-only - -#ifndef ASSEMBLE_MIPS_H -#define ASSEMBLE_MIPS_H - -#include - -RZ_IPI int mips_assemble_opcode(const char *str, ut64 pc, ut8 *out); - -#endif /* ASSEMBLE_MIPS_H */ diff --git a/librz/arch/isa/mips/mips_esil.c b/librz/arch/isa/mips/mips_esil.c new file mode 100644 index 00000000000..422968f2233 --- /dev/null +++ b/librz/arch/isa/mips/mips_esil.c @@ -0,0 +1,579 @@ +// SPDX-FileCopyrightText: 2013-2019 pancake +// SPDX-License-Identifier: LGPL-3.0-only + +#include "mips_internal.h" +#include +#include + +#define OPCOUNT() insn->detail->mips.op_count +#define REGID(x) insn->detail->mips.operands[x].reg +#define REG(x) cs_reg_name(*handle, insn->detail->mips.operands[x].reg) +#define IMM(x) insn->detail->mips.operands[x].imm + +// ESIL macros: +// put the sign bit on the stack +#define ES_IS_NEGATIVE(arg) "1," arg ",<<<,1,&" + +// call with delay slot +#define ES_CALL_DR(ra, addr) "pc,4,+," ra ",=," ES_J(addr) +#define ES_CALL_D(addr) ES_CALL_DR("ra", addr) + +// call without delay slot +#define ES_CALL_NDR(ra, addr) "pc," ra ",=," ES_J(addr) +#define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr) + +#define USE_DS 0 +#if USE_DS +// emit ERR trap if executed in a delay slot +#define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,}," +// jump to address +#define ES_J(addr) addr ",SETJT,1,SETD" +#else +#define ES_TRAP_DS() "" +#define ES_J(addr) addr ",pc,=" +#endif + +#define ES_B(x) "0xff," x ",&" +#define ES_H(x) "0xffff," x ",&" +#define ES_W(x) "0xffffffff," x ",&" + +// sign extend 32 -> 64 +#define ES_SIGN32_64(arg) es_sign_n_64(a, op, arg, 32) +#define ES_SIGN16_64(arg) es_sign_n_64(a, op, arg, 16) + +#define ES_ADD_CK32_OVERF(x, y, z) es_add_ck(op, x, y, z, 32) +#define ES_ADD_CK64_OVERF(x, y, z) es_add_ck(op, x, y, z, 64) + +static inline void es_sign_n_64(RzAnalysis *a, RzAnalysisOp *op, const char *arg, int bit) { + if (a->bits == 64) { + rz_strbuf_appendf(&op->esil, ",%d,%s,~,%s,=,", bit, arg, arg); + } else { + rz_strbuf_append(&op->esil, ","); + } +} + +static inline void es_add_ck(RzAnalysisOp *op, const char *a1, const char *a2, const char *re, int bit) { + ut64 mask = 1ULL << (bit - 1); + rz_strbuf_appendf(&op->esil, + "%d,0x%" PFMT64x ",%s,%s,^,&,>>,%d,0x%" PFMT64x ",%s,%s,+,&,>>,|,1,==,$z,?{,$$,1,TRAP,}{,%s,%s,+,%s,=,}", + bit - 2, mask, a1, a2, bit - 1, mask, a1, a2, a1, a2, re); +} + +#if CS_NEXT_VERSION < 6 +#define PROTECT_ZERO() \ + if (REGID(0) == MIPS_REG_ZERO) { \ + rz_strbuf_appendf(&op->esil, ","); \ + } else +#else +#define PROTECT_ZERO() \ + if (REGID(0) == MIPS_REG_ZERO || \ + REGID(0) == MIPS_REG_ZERO_64) { \ + rz_strbuf_appendf(&op->esil, ","); \ + } else +#endif // CS_NEXT_VERSION + +#define ESIL_LOAD(size) \ + PROTECT_ZERO() { \ + rz_strbuf_appendf(&op->esil, "%s,[" size "],%s,=", \ + ARG(1), REG(0)); \ + } + +static const char *arg(csh *handle, cs_insn *insn, char *buf, int n) { + *buf = 0; + switch (insn->detail->mips.operands[n].type) { + case MIPS_OP_INVALID: + break; + case MIPS_OP_REG: + sprintf(buf, "%s", + cs_reg_name(*handle, + insn->detail->mips.operands[n].reg)); + break; + case MIPS_OP_IMM: { + st64 x = (st64)insn->detail->mips.operands[n].imm; + sprintf(buf, "%" PFMT64d, x); + } break; + case MIPS_OP_MEM: { + int disp = insn->detail->mips.operands[n].mem.disp; + if (disp < 0) { + sprintf(buf, "%" PFMT64d ",%s,-", + (ut64)-insn->detail->mips.operands[n].mem.disp, + cs_reg_name(*handle, + insn->detail->mips.operands[n].mem.base)); + } else { + sprintf(buf, "0x%" PFMT64x ",%s,+", + (ut64)insn->detail->mips.operands[n].mem.disp, + cs_reg_name(*handle, + insn->detail->mips.operands[n].mem.base)); + } + } break; + } + return buf; +} + +#define ARG(x) (*str[x] != 0) ? str[x] : arg(handle, insn, str[x], x) + +RZ_IPI int analyze_op_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { + char str[8][32] = { { 0 } }; + + rz_strbuf_init(&op->esil); + rz_strbuf_set(&op->esil, ""); + + if (!insn) { + return 0; + } + + // caching operands + for (int i = 0; i < insn->detail->mips.op_count && i < 8; i++) { + *str[i] = 0; + ARG(i); + } + { + switch (insn->id) { + case MIPS_INS_NOP: + rz_strbuf_setf(&op->esil, ","); + break; + case MIPS_INS_BREAK: + rz_strbuf_setf(&op->esil, "%" PFMT64d ",%" PFMT64d ",TRAP", (st64)IMM(0), (st64)IMM(0)); + break; + case MIPS_INS_SD: + rz_strbuf_appendf(&op->esil, "%s,%s,=[8]", + ARG(0), ARG(1)); + break; + case MIPS_INS_SW: + case MIPS_INS_SWL: + case MIPS_INS_SWR: + rz_strbuf_appendf(&op->esil, "%s,%s,=[4]", + ARG(0), ARG(1)); + break; + case MIPS_INS_SH: + rz_strbuf_appendf(&op->esil, "%s,%s,=[2]", + ARG(0), ARG(1)); + break; + case MIPS_INS_SWC1: + case MIPS_INS_SWC2: + rz_strbuf_setf(&op->esil, "%s,$", ARG(1)); + break; + case MIPS_INS_SB: + rz_strbuf_appendf(&op->esil, "%s,%s,=[1]", + ARG(0), ARG(1)); + break; +#if CS_NEXT_VERSION >= 6 + case MIPS_INS_CMPU_LE_QB: + case MIPS_INS_CMPGU_LE_QB: + case MIPS_INS_CMPGDU_LE_QB: + rz_strbuf_appendf(&op->esil, "%s,%s,<=", ARG(1), ARG(0)); + break; + case MIPS_INS_CMPU_LT_QB: + case MIPS_INS_CMPGU_LT_QB: + case MIPS_INS_CMPGDU_LT_QB: + rz_strbuf_appendf(&op->esil, "%s,%s,<", ARG(1), ARG(0)); + break; +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_CMP: +#if CS_NEXT_VERSION < 6 + case MIPS_INS_CMPU: + case MIPS_INS_CMPGU: + case MIPS_INS_CMPGDU: +#else + case MIPS_INS_CMPU_EQ_QB: + case MIPS_INS_CMPGU_EQ_QB: + case MIPS_INS_CMPGDU_EQ_QB: +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_CMPI: + rz_strbuf_appendf(&op->esil, "%s,%s,==", ARG(1), ARG(0)); + break; + case MIPS_INS_DSRA: + rz_strbuf_appendf(&op->esil, + "%s,%s,>>,31,%s,>>,?{,32,%s,32,-,0xffffffff,<<,0xffffffff,&,<<,}{,0,},|,%s,=", + ARG(2), ARG(1), ARG(1), ARG(2), ARG(0)); + break; +#if CS_NEXT_VERSION < 6 + case MIPS_INS_SHRAV: + case MIPS_INS_SHRAV_R: + case MIPS_INS_SHRA: + case MIPS_INS_SHRA_R: +#else + case MIPS_INS_SHRA_PH: + case MIPS_INS_SHRA_QB: + case MIPS_INS_SHRA_R_PH: + case MIPS_INS_SHRA_R_QB: + case MIPS_INS_SHRA_R_W: + case MIPS_INS_SHRAV_PH: + case MIPS_INS_SHRAV_QB: + case MIPS_INS_SHRAV_R_PH: + case MIPS_INS_SHRAV_R_QB: + case MIPS_INS_SHRAV_R_W: +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_SRA: + rz_strbuf_appendf(&op->esil, + "0xffffffff,%s,%s,>>,&,31,%s,>>,?{,%s,32,-,0xffffffff,<<,0xffffffff,&,}{,0,},|,%s,=", + ARG(2), ARG(1), ARG(1), ARG(2), ARG(0)); + break; +#if CS_NEXT_VERSION < 6 + case MIPS_INS_SHRL: +#else + case MIPS_INS_SHRL_PH: + case MIPS_INS_SHRL_QB: + case MIPS_INS_SHRLV_PH: + case MIPS_INS_SHRLV_QB: +#endif /* CS_NEXT_VERSION */ + // suffix 'S' forces conditional flag to be updated + case MIPS_INS_SRLV: + case MIPS_INS_SRL: + rz_strbuf_appendf(&op->esil, "%s,%s,>>,%s,=", ARG(2), ARG(1), ARG(0)); + break; + case MIPS_INS_SLLV: + case MIPS_INS_SLL: +#if CS_NEXT_VERSION < 6 + rz_strbuf_appendf(&op->esil, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0)); +#else + if (REGID(0) == MIPS_REG_INVALID) { + // NOP + rz_strbuf_setf(&op->esil, ","); + } else { + rz_strbuf_appendf(&op->esil, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0)); + } +#endif /* CS_NEXT_VERSION */ + break; + case MIPS_INS_BAL: + case MIPS_INS_JAL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), ARG(0)); + break; + case MIPS_INS_JALR: + case MIPS_INS_JALRS: + if (OPCOUNT() < 2) { + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), ARG(0)); + } else { + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_DR("%s", "%s"), ARG(0), ARG(1)); + } + } + break; + case MIPS_INS_JALRC: // no delay + if (OPCOUNT() < 2) { + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_ND("%s"), ARG(0)); + } else { + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_NDR("%s", "%s"), ARG(0), ARG(1)); + } + } + break; + case MIPS_INS_JRADDIUSP: + // increment stackpointer in X and jump to %ra + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,sp,+=," ES_J("ra"), ARG(0)); + break; + case MIPS_INS_JR: + case MIPS_INS_JRC: + case MIPS_INS_J: + case MIPS_INS_B: // ??? + // jump to address with conditional + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_J("%s"), ARG(0)); + break; + case MIPS_INS_BNE: // bne $s, $t, offset + case MIPS_INS_BNEL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,!,?{," ES_J("%s") ",}", + ARG(0), ARG(1), ARG(2)); + break; + case MIPS_INS_BEQ: + case MIPS_INS_BEQL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,?{," ES_J("%s") ",}", + ARG(0), ARG(1), ARG(2)); + break; +#if CS_NEXT_VERSION < 6 + case MIPS_INS_BZ: +#else + case MIPS_INS_BZ_B: + case MIPS_INS_BZ_D: + case MIPS_INS_BZ_H: + case MIPS_INS_BZ_V: + case MIPS_INS_BZ_W: +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_BEQZ: + case MIPS_INS_BEQZC: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,?{," ES_J("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BNEZ: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,!,?{," ES_J("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BEQZALC: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,?{," ES_CALL_ND("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BLEZ: + case MIPS_INS_BLEZC: + case MIPS_INS_BLEZL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{," ES_J("%s") ",BREAK,},", + ARG(0), ARG(1)); + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BGEZ: + case MIPS_INS_BGEZC: + case MIPS_INS_BGEZL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BGEZAL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BGEZALC: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_ND("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BGTZALC: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{,BREAK,},", ARG(0)); + rz_strbuf_appendf(&op->esil, "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_ND("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BLTZAL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}", ARG(0), ARG(1)); + break; + case MIPS_INS_BLTZ: + case MIPS_INS_BLTZC: + case MIPS_INS_BLTZL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BGTZ: + case MIPS_INS_BGTZC: + case MIPS_INS_BGTZL: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{,BREAK,},", ARG(0)); + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", + ARG(0), ARG(1)); + break; + case MIPS_INS_BTEQZ: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,t,==,$z,?{," ES_J("%s") ",}", ARG(0)); + break; + case MIPS_INS_BTNEZ: + rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,t,==,$z,!,?{," ES_J("%s") ",}", ARG(0)); + break; +#if CS_NEXT_VERSION < 6 + case MIPS_INS_MOV: +#else + case MIPS_INS_MOV_D: + case MIPS_INS_MOV_S: +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_MOVE: + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "%s,%s,=", ARG(1), REG(0)); + } + break; + case MIPS_INS_MOVZ: + case MIPS_INS_MOVF: + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "0,%s,==,$z,?{,%s,%s,=,}", + ARG(2), ARG(1), REG(0)); + } + break; + case MIPS_INS_MOVT: + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "1,%s,==,$z,?{,%s,%s,=,}", + ARG(2), ARG(1), REG(0)); + } + break; +#if CS_NEXT_VERSION < 6 + case MIPS_INS_FSUB: +#else + case MIPS_INS_FSUB_D: + case MIPS_INS_FSUB_W: +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_SUB: + case MIPS_INS_SUBU: + case MIPS_INS_DSUB: + case MIPS_INS_DSUBU: + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", + ARG(2), ARG(1), ARG(0)); + } + break; +#if CS_NEXT_VERSION < 6 + case MIPS_INS_NEGU: +#else + case MIPS_INS_NEG_D: + case MIPS_INS_NEG_S: +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_NEG: + rz_strbuf_appendf(&op->esil, "%s,0,-,%s,=,", + ARG(1), ARG(0)); + break; + + /** signed -- sets overflow flag */ + case MIPS_INS_ADD: { + PROTECT_ZERO() { + ES_ADD_CK32_OVERF(ARG(1), ARG(2), ARG(0)); + } + } break; + case MIPS_INS_ADDI: + PROTECT_ZERO() { + ES_ADD_CK32_OVERF(ARG(1), ARG(2), ARG(0)); + } + break; + case MIPS_INS_DADD: + case MIPS_INS_DADDI: + ES_ADD_CK64_OVERF(ARG(1), ARG(2), ARG(0)); + break; + /** unsigned */ + case MIPS_INS_DADDU: + case MIPS_INS_ADDU: + case MIPS_INS_ADDIU: + case MIPS_INS_DADDIU: { + const char *arg0 = ARG(0); + const char *arg1 = ARG(1); + const char *arg2 = ARG(2); + PROTECT_ZERO() { + if (*arg2 == '-') { + rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", + arg2 + 1, arg1, arg0); + } else { + rz_strbuf_appendf(&op->esil, "%s,%s,+,%s,=", + arg2, arg1, arg0); + } + } + } break; + case MIPS_INS_LI: +#if CS_NEXT_VERSION < 6 + case MIPS_INS_LDI: +#else + case MIPS_INS_LDI_B: + case MIPS_INS_LDI_D: + case MIPS_INS_LDI_H: + case MIPS_INS_LDI_W: +#endif /* CS_NEXT_VERSION */ + rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",%s,=", (ut64)IMM(1), ARG(0)); + break; + case MIPS_INS_LUI: + rz_strbuf_appendf(&op->esil, "0x%" PFMT64x "0000,%s,=", (ut64)IMM(1), ARG(0)); + break; + case MIPS_INS_LB: + op->sign = true; + ESIL_LOAD("1"); + break; + case MIPS_INS_LBU: + case MIPS_INS_LBUX: + // one of these is wrong + ESIL_LOAD("1"); + break; + case MIPS_INS_LL: + case MIPS_INS_LW: + case MIPS_INS_LWC1: + case MIPS_INS_LWC2: + case MIPS_INS_LWL: + case MIPS_INS_LWR: + case MIPS_INS_LWU: + case MIPS_INS_LWXC1: + ESIL_LOAD("4"); + break; + + case MIPS_INS_LD: + case MIPS_INS_LDC1: + case MIPS_INS_LDC2: + case MIPS_INS_LDL: + case MIPS_INS_LDR: + case MIPS_INS_LDXC1: + case MIPS_INS_LLD: + ESIL_LOAD("8"); + break; + + case MIPS_INS_LWX: + case MIPS_INS_LH: + case MIPS_INS_LHU: + case MIPS_INS_LHX: + ESIL_LOAD("2"); + break; + + case MIPS_INS_AND: + case MIPS_INS_ANDI: { + const char *arg0 = ARG(0); + const char *arg1 = ARG(1); + const char *arg2 = ARG(2); + if (!strcmp(arg0, arg1)) { + rz_strbuf_appendf(&op->esil, "%s,%s,&=", arg2, arg1); + } else { + rz_strbuf_appendf(&op->esil, "%s,%s,&,%s,=", arg2, arg1, arg0); + } + } break; + case MIPS_INS_OR: + case MIPS_INS_ORI: { + const char *arg0 = ARG(0); + const char *arg1 = ARG(1); + const char *arg2 = ARG(2); + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "%s,%s,|,%s,=", + arg2, arg1, arg0); + } + } break; + case MIPS_INS_XOR: + case MIPS_INS_XORI: { + const char *arg0 = ARG(0); + const char *arg1 = ARG(1); + const char *arg2 = ARG(2); + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "%s,%s,^,%s,=", + arg2, arg1, arg0); + } + } break; + case MIPS_INS_NOR: { + const char *arg0 = ARG(0); + const char *arg1 = ARG(1); + const char *arg2 = ARG(2); + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "%s,%s,|,0xffffffff,^,%s,=", + arg2, arg1, arg0); + } + } break; + case MIPS_INS_SLT: + case MIPS_INS_SLTI: + if (OPCOUNT() < 3) { + rz_strbuf_appendf(&op->esil, "%s,%s,<,t,=", ARG(1), ARG(0)); + } else { + rz_strbuf_appendf(&op->esil, "%s,%s,<,%s,=", ARG(2), ARG(1), ARG(0)); + } + break; + case MIPS_INS_SLTU: + case MIPS_INS_SLTIU: + if (OPCOUNT() < 3) { + rz_strbuf_appendf(&op->esil, ES_W("%s") "," ES_W("%s") ",<,t,=", + ARG(1), ARG(0)); + } else { + rz_strbuf_appendf(&op->esil, ES_W("%s") "," ES_W("%s") ",<,%s,=", + ARG(2), ARG(1), ARG(0)); + } + break; + case MIPS_INS_MUL: + rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",%s,=", ARG(1), ARG(2), ARG(0)); + ES_SIGN32_64(ARG(0)); + break; + case MIPS_INS_MULT: + case MIPS_INS_MULTU: + rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",lo,=", ARG(0), ARG(1)); + ES_SIGN32_64("lo"); + rz_strbuf_appendf(&op->esil, ES_W("32,%s,%s,*,>>") ",hi,=", ARG(0), ARG(1)); + ES_SIGN32_64("hi"); + break; + case MIPS_INS_MFLO: + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "lo,%s,=", REG(0)); + } + break; + case MIPS_INS_MFHI: + PROTECT_ZERO() { + rz_strbuf_appendf(&op->esil, "hi,%s,=", REG(0)); + } + break; + case MIPS_INS_MTLO: + rz_strbuf_appendf(&op->esil, "%s,lo,=", REG(0)); + ES_SIGN32_64("lo"); + break; + case MIPS_INS_MTHI: + rz_strbuf_appendf(&op->esil, "%s,hi,=", REG(0)); + ES_SIGN32_64("hi"); + break; + default: + return -1; + } + } + return 0; +} diff --git a/librz/arch/isa/mips/mips_internal.h b/librz/arch/isa/mips/mips_internal.h new file mode 100644 index 00000000000..dd2d3e5e40e --- /dev/null +++ b/librz/arch/isa/mips/mips_internal.h @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2012-2018 pancake +// SPDX-License-Identifier: LGPL-3.0-only + +#ifndef MIPS_INTERNAL_H +#define MIPS_INTERNAL_H + +#include +#include +#include + +RZ_IPI int mips_assemble_opcode(const char *str, ut64 pc, ut8 *out); +RZ_IPI int analyze_op_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn); + +#endif /* MIPS_INTERNAL_H */ diff --git a/librz/arch/isa_gnu/mips/mips-dis.c b/librz/arch/isa_gnu/mips/mips-dis.c deleted file mode 100644 index 6dd086cd5a1..00000000000 --- a/librz/arch/isa_gnu/mips/mips-dis.c +++ /dev/null @@ -1,2163 +0,0 @@ -/* Print mips instructions for GDB, the GNU debugger, or for objdump. - Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2005, 2007 - Free Software Foundation, Inc. - Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp). - - This file is part of the GNU opcodes library. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - It is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - MA 02110-1301, USA. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* FIXME: These are needed to figure out if the code is mips16 or - not. The low bit of the address is often a good indicator. No - symbol table is available when this code runs out in an embedded - system as when it is used for disassembler support in a monitor. */ - -#include -#if !defined(EMBEDDED_ENV) -#define SYMTAB_AVAILABLE 1 -#include -#endif - -/* Mips instructions are at maximum this many bytes long. */ -#define INSNLEN 4 - - -/* FIXME: These should be shared with gdb somehow. */ - -struct mips_cp0sel_name -{ - unsigned int cp0reg; - unsigned int sel; - const char * const name; -}; - -/* The mips16 registers. */ -static const unsigned int mips16_to_32_reg_map[] = -{ - 16, 17, 2, 3, 4, 5, 6, 7 -}; - -#define mips16_reg_names(rn) mips_gpr_names[mips16_to_32_reg_map[rn]] - - -static const char * const mips_gpr_names_numeric[32] = -{ - "$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" -}; - -const char * const mips_gpr_names_oldabi[32] = -{ - "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" -}; - -const char * const mips_gpr_names_newabi[32] = -{ - "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" -}; - -static const char * const mips_fpr_names_numeric[32] = -{ - "$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" -}; - -static const char * const mips_fpr_names_32[32] = -{ - "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f", - "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f", - "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f", - "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f" -}; - -static const char * const mips_fpr_names_n32[32] = -{ - "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3", - "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3", - "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9", - "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13" -}; - -static const char * const mips_fpr_names_64[32] = -{ - "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3", - "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3", - "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11", - "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7" -}; - -static const char * const mips_cp0_names_numeric[32] = -{ - "$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" -}; - -static const char * const mips_cp0_names_mips3264[32] = -{ - "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", - "c0_context", "c0_pagemask", "c0_wired", "$7", - "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare", - "c0_status", "c0_cause", "c0_epc", "c0_prid", - "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi", - "c0_xcontext", "$21", "$22", "c0_debug", - "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr", - "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave", -}; - -static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] = -{ - { 16, 1, "c0_config1" }, - { 16, 2, "c0_config2" }, - { 16, 3, "c0_config3" }, - { 18, 1, "c0_watchlo,1" }, - { 18, 2, "c0_watchlo,2" }, - { 18, 3, "c0_watchlo,3" }, - { 18, 4, "c0_watchlo,4" }, - { 18, 5, "c0_watchlo,5" }, - { 18, 6, "c0_watchlo,6" }, - { 18, 7, "c0_watchlo,7" }, - { 19, 1, "c0_watchhi,1" }, - { 19, 2, "c0_watchhi,2" }, - { 19, 3, "c0_watchhi,3" }, - { 19, 4, "c0_watchhi,4" }, - { 19, 5, "c0_watchhi,5" }, - { 19, 6, "c0_watchhi,6" }, - { 19, 7, "c0_watchhi,7" }, - { 25, 1, "c0_perfcnt,1" }, - { 25, 2, "c0_perfcnt,2" }, - { 25, 3, "c0_perfcnt,3" }, - { 25, 4, "c0_perfcnt,4" }, - { 25, 5, "c0_perfcnt,5" }, - { 25, 6, "c0_perfcnt,6" }, - { 25, 7, "c0_perfcnt,7" }, - { 27, 1, "c0_cacheerr,1" }, - { 27, 2, "c0_cacheerr,2" }, - { 27, 3, "c0_cacheerr,3" }, - { 28, 1, "c0_datalo" }, - { 29, 1, "c0_datahi" } -}; - -static const char * const mips_cp0_names_mips3264r2[32] = -{ - "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", - "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena", - "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare", - "c0_status", "c0_cause", "c0_epc", "c0_prid", - "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi", - "c0_xcontext", "$21", "$22", "c0_debug", - "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr", - "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave", -}; - -static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] = -{ - { 4, 1, "c0_contextconfig" }, - { 0, 1, "c0_mvpcontrol" }, - { 0, 2, "c0_mvpconf0" }, - { 0, 3, "c0_mvpconf1" }, - { 1, 1, "c0_vpecontrol" }, - { 1, 2, "c0_vpeconf0" }, - { 1, 3, "c0_vpeconf1" }, - { 1, 4, "c0_yqmask" }, - { 1, 5, "c0_vpeschedule" }, - { 1, 6, "c0_vpeschefback" }, - { 2, 1, "c0_tcstatus" }, - { 2, 2, "c0_tcbind" }, - { 2, 3, "c0_tcrestart" }, - { 2, 4, "c0_tchalt" }, - { 2, 5, "c0_tccontext" }, - { 2, 6, "c0_tcschedule" }, - { 2, 7, "c0_tcschefback" }, - { 5, 1, "c0_pagegrain" }, - { 6, 1, "c0_srsconf0" }, - { 6, 2, "c0_srsconf1" }, - { 6, 3, "c0_srsconf2" }, - { 6, 4, "c0_srsconf3" }, - { 6, 5, "c0_srsconf4" }, - { 12, 1, "c0_intctl" }, - { 12, 2, "c0_srsctl" }, - { 12, 3, "c0_srsmap" }, - { 15, 1, "c0_ebase" }, - { 16, 1, "c0_config1" }, - { 16, 2, "c0_config2" }, - { 16, 3, "c0_config3" }, - { 18, 1, "c0_watchlo,1" }, - { 18, 2, "c0_watchlo,2" }, - { 18, 3, "c0_watchlo,3" }, - { 18, 4, "c0_watchlo,4" }, - { 18, 5, "c0_watchlo,5" }, - { 18, 6, "c0_watchlo,6" }, - { 18, 7, "c0_watchlo,7" }, - { 19, 1, "c0_watchhi,1" }, - { 19, 2, "c0_watchhi,2" }, - { 19, 3, "c0_watchhi,3" }, - { 19, 4, "c0_watchhi,4" }, - { 19, 5, "c0_watchhi,5" }, - { 19, 6, "c0_watchhi,6" }, - { 19, 7, "c0_watchhi,7" }, - { 23, 1, "c0_tracecontrol" }, - { 23, 2, "c0_tracecontrol2" }, - { 23, 3, "c0_usertracedata" }, - { 23, 4, "c0_tracebpc" }, - { 25, 1, "c0_perfcnt,1" }, - { 25, 2, "c0_perfcnt,2" }, - { 25, 3, "c0_perfcnt,3" }, - { 25, 4, "c0_perfcnt,4" }, - { 25, 5, "c0_perfcnt,5" }, - { 25, 6, "c0_perfcnt,6" }, - { 25, 7, "c0_perfcnt,7" }, - { 27, 1, "c0_cacheerr,1" }, - { 27, 2, "c0_cacheerr,2" }, - { 27, 3, "c0_cacheerr,3" }, - { 28, 1, "c0_datalo" }, - { 28, 2, "c0_taglo1" }, - { 28, 3, "c0_datalo1" }, - { 28, 4, "c0_taglo2" }, - { 28, 5, "c0_datalo2" }, - { 28, 6, "c0_taglo3" }, - { 28, 7, "c0_datalo3" }, - { 29, 1, "c0_datahi" }, - { 29, 2, "c0_taghi1" }, - { 29, 3, "c0_datahi1" }, - { 29, 4, "c0_taghi2" }, - { 29, 5, "c0_datahi2" }, - { 29, 6, "c0_taghi3" }, - { 29, 7, "c0_datahi3" }, -}; - -/* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */ -static const char * const mips_cp0_names_sb1[32] = -{ - "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1", - "c0_context", "c0_pagemask", "c0_wired", "$7", - "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare", - "c0_status", "c0_cause", "c0_epc", "c0_prid", - "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi", - "c0_xcontext", "$21", "$22", "c0_debug", - "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i", - "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave", -}; - -static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] = -{ - { 16, 1, "c0_config1" }, - { 18, 1, "c0_watchlo,1" }, - { 19, 1, "c0_watchhi,1" }, - { 22, 0, "c0_perftrace" }, - { 23, 3, "c0_edebug" }, - { 25, 1, "c0_perfcnt,1" }, - { 25, 2, "c0_perfcnt,2" }, - { 25, 3, "c0_perfcnt,3" }, - { 25, 4, "c0_perfcnt,4" }, - { 25, 5, "c0_perfcnt,5" }, - { 25, 6, "c0_perfcnt,6" }, - { 25, 7, "c0_perfcnt,7" }, - { 26, 1, "c0_buserr_pa" }, - { 27, 1, "c0_cacheerr_d" }, - { 27, 3, "c0_cacheerr_d_pa" }, - { 28, 1, "c0_datalo_i" }, - { 28, 2, "c0_taglo_d" }, - { 28, 3, "c0_datalo_d" }, - { 29, 1, "c0_datahi_i" }, - { 29, 2, "c0_taghi_d" }, - { 29, 3, "c0_datahi_d" }, -}; - -static const char * const mips_hwr_names_numeric[32] = -{ - "$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" -}; - -static const char * const mips_hwr_names_mips3264r2[32] = -{ - "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres", - "$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" -}; - -struct mips_abi_choice -{ - const char * name; - const char * const *gpr_names; - const char * const *fpr_names; -}; - -struct mips_abi_choice mips_abi_choices[] = -{ - { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric }, - { "o32", mips_gpr_names_oldabi, mips_fpr_names_32 }, - { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 }, - { "n64", mips_gpr_names_newabi, mips_fpr_names_64 }, -}; - -struct mips_arch_choice -{ - const char *name; - int bfd_mach_valid; - unsigned long bfd_mach; - int processor; - int isa; - const char * const *cp0_names; - const struct mips_cp0sel_name *cp0sel_names; - unsigned int cp0sel_names_len; - const char * const *hwr_names; -}; - -const struct mips_arch_choice mips_arch_choices[] = -{ - { "numeric", 0, 0, 0, 0, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - - { "r3000", 1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r3900", 1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r4000", 1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r4010", 1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "rm9000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, - - /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs. - Note that MIPS-3D and MDMX are not applicable to MIPS32. (See - _MIPS32 Architecture For Programmers Volume I: Introduction to the - MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95), - page 1. */ - { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32, - ISA_MIPS32 | INSN_MIPS16 | INSN_SMARTMIPS, - mips_cp0_names_mips3264, - mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264), - mips_hwr_names_numeric }, - - { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2, - (ISA_MIPS32R2 | INSN_MIPS16 | INSN_SMARTMIPS | INSN_DSP | INSN_DSPR2 - | INSN_MIPS3D | INSN_MT), - mips_cp0_names_mips3264r2, - mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2), - mips_hwr_names_mips3264r2 }, - - /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */ - { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64, - ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX, - mips_cp0_names_mips3264, - mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264), - mips_hwr_names_numeric }, - - { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2, - (ISA_MIPS64R2 | INSN_MIPS16 | INSN_MIPS3D | INSN_DSP | INSN_DSPR2 - | INSN_DSP64 | INSN_MT | INSN_MDMX), - mips_cp0_names_mips3264r2, - mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2), - mips_hwr_names_mips3264r2 }, - - { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1, - ISA_MIPS64 | INSN_MIPS3D | INSN_SB1, - mips_cp0_names_sb1, - mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1), - mips_hwr_names_numeric }, - - { "loongson2e", 1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E, - ISA_MIPS3 | INSN_LOONGSON_2E, - mips_cp0_names_numeric, - NULL, 0, mips_hwr_names_numeric }, - - { "loongson2f", 1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F, - ISA_MIPS64 | INSN_LOONGSON_2F, - mips_cp0_names_numeric, - NULL, 0, mips_hwr_names_numeric }, - - /* This entry, mips16, is here only for ISA/processor selection; do - not print its name. */ - { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3 | INSN_MIPS16, - mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, -}; - -/* ISA and processor type to disassemble for, and register names to use. - set_default_mips_dis_options and parse_mips_dis_options fill in these - values. */ -static int mips_processor; -static int mips_isa; -static const char * const *mips_gpr_names; -static const char * const *mips_fpr_names; -static const char * const *mips_cp0_names; -static const struct mips_cp0sel_name *mips_cp0sel_names; -static int mips_cp0sel_names_len; -static const char * const *mips_hwr_names; - -/* Other options */ -static int no_aliases; /* If set disassemble as most general inst. */ - -static const struct mips_abi_choice * -choose_abi_by_name (const char *name, unsigned int namelen) -{ - const struct mips_abi_choice *c; - unsigned int i; - - for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && !c; i++) { - if (strncmp (mips_abi_choices[i].name, name, namelen) == 0 && strlen (mips_abi_choices[i].name) == namelen) { - c = &mips_abi_choices[i]; - } - } - - return c; -} - -static const struct mips_arch_choice * -choose_arch_by_name (const char *name, unsigned int namelen) -{ - const struct mips_arch_choice *c = NULL; - unsigned int i; - - for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && !c; i++) { - if (strncmp (mips_arch_choices[i].name, name, namelen) == 0 && strlen (mips_arch_choices[i].name) == namelen) { - c = &mips_arch_choices[i]; - } - } - - return c; -} - -static const struct mips_arch_choice * -choose_arch_by_number (unsigned long mach) -{ - static unsigned long hint_bfd_mach; - static const struct mips_arch_choice *hint_arch_choice; - const struct mips_arch_choice *c; - unsigned int i; - - /* We optimize this because even if the user specifies no - flags, this will be done for every instruction! */ - if (hint_bfd_mach == mach && hint_arch_choice != NULL && hint_arch_choice->bfd_mach == hint_bfd_mach) { - return hint_arch_choice; - } - - for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && !c; i++) - { - if (mips_arch_choices[i].bfd_mach_valid - && mips_arch_choices[i].bfd_mach == mach) - { - c = &mips_arch_choices[i]; - hint_bfd_mach = mach; - hint_arch_choice = c; - } - } - return c; -} - -/* Check if the object uses NewABI conventions. */ - -static int -is_newabi (Elf_Internal_Ehdr *header) -{ - /* There are no old-style ABIs which use 64-bit ELF. */ - if (header->e_ident[EI_CLASS] == ELFCLASS64) { - return 1; - } - - /* If a 32-bit ELF file, n32 is a new-style ABI. */ - if ((header->e_flags & EF_MIPS_ABI2) != 0) { - return 1; - } - - return 0; -} - -static void -set_default_mips_dis_options (struct disassemble_info *info) -{ - const struct mips_arch_choice *chosen_arch; - - /* Defaults: mipsIII/r3000 (?!), (o)32-style ("oldabi") GPR names, - and numeric FPR, CP0 register, and HWR names. */ - mips_isa = ISA_MIPS3; - mips_processor = CPU_LOONGSON_2F; // R3000 - mips_gpr_names = mips_gpr_names_oldabi; - mips_fpr_names = mips_fpr_names_numeric; - mips_cp0_names = mips_cp0_names_numeric; - mips_cp0sel_names = NULL; - mips_cp0sel_names_len = 0; - mips_hwr_names = mips_hwr_names_numeric; - no_aliases = 0; - - /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */ - if (info->flavour == bfd_target_elf_flavour && info->section != NULL) - { - Elf_Internal_Ehdr *header; - - header = elf_elfheader (info->section->owner); - if (is_newabi (header)) { - mips_gpr_names = mips_gpr_names_newabi; - } - } - - /* Set ISA, architecture, and cp0 register names as best we can. */ -#if ! SYMTAB_AVAILABLE - /* This is running out on a target machine, not in a host tool. - FIXME: Where does mips_target_info come from? */ - target_processor = mips_target_info.processor; - mips_isa = mips_target_info.isa; -#else - chosen_arch = choose_arch_by_number (info->mach); - if (chosen_arch != NULL) - { - mips_processor = chosen_arch->processor; - mips_isa = chosen_arch->isa; - mips_cp0_names = chosen_arch->cp0_names; - mips_cp0sel_names = chosen_arch->cp0sel_names; - mips_cp0sel_names_len = chosen_arch->cp0sel_names_len; - mips_hwr_names = chosen_arch->hwr_names; - } -#endif -} - -static void -parse_mips_dis_option (const char *option, unsigned int len) -{ - unsigned int i, optionlen, vallen; - const char *val; - const struct mips_abi_choice *chosen_abi; - const struct mips_arch_choice *chosen_arch; - - /* Try to match options that are simple flags - if (CONST_STRNEQ (option, "no-aliases")) - { - no_aliases = 1; - return; - } */ - - /* Look for the = that delimits the end of the option name. */ - for (i = 0; i < len; i++) { - if (option[i] == '=') { - break; - } - } - - if (i == 0) { /* Invalid option: no name before '='. */ - return; - } - if (i == len) { /* Invalid option: no '='. */ - return; - } - if (i == (len - 1)) { /* Invalid option: no value after '='. */ - return; - } - - optionlen = i; - val = option + (optionlen + 1); - vallen = len - (optionlen + 1); - - if (strlen ("abi") == optionlen - && !strncmp ("abi", option, optionlen)) { - chosen_abi = choose_abi_by_name (val, vallen); - if (chosen_abi) { - mips_gpr_names = chosen_abi->gpr_names; - mips_fpr_names = chosen_abi->fpr_names; - } - return; - } - - if (strncmp ("gpr-names", option, optionlen) == 0 - && strlen ("gpr-names") == optionlen) - { - chosen_abi = choose_abi_by_name (val, vallen); - if (chosen_abi != NULL) { - mips_gpr_names = chosen_abi->gpr_names; - } - return; - } - - if (strncmp ("fpr-names", option, optionlen) == 0 - && strlen ("fpr-names") == optionlen) - { - chosen_abi = choose_abi_by_name (val, vallen); - if (chosen_abi != NULL) { - mips_fpr_names = chosen_abi->fpr_names; - } - return; - } - - if (strncmp ("cp0-names", option, optionlen) == 0 - && strlen ("cp0-names") == optionlen) - { - chosen_arch = choose_arch_by_name (val, vallen); - if (chosen_arch != NULL) - { - mips_cp0_names = chosen_arch->cp0_names; - mips_cp0sel_names = chosen_arch->cp0sel_names; - mips_cp0sel_names_len = chosen_arch->cp0sel_names_len; - } - return; - } - - if (strncmp ("hwr-names", option, optionlen) == 0 - && strlen ("hwr-names") == optionlen) - { - chosen_arch = choose_arch_by_name (val, vallen); - if (chosen_arch != NULL) { - mips_hwr_names = chosen_arch->hwr_names; - } - return; - } - - if (strncmp ("reg-names", option, optionlen) == 0 - && strlen ("reg-names") == optionlen) - { - /* We check both ABI and ARCH here unconditionally, so - that "numeric" will do the desirable thing: select - numeric register names for all registers. Other than - that, a given name probably won't match both. */ - chosen_abi = choose_abi_by_name (val, vallen); - if (chosen_abi != NULL) - { - mips_gpr_names = chosen_abi->gpr_names; - mips_fpr_names = chosen_abi->fpr_names; - } - chosen_arch = choose_arch_by_name (val, vallen); - if (chosen_arch != NULL) - { - mips_cp0_names = chosen_arch->cp0_names; - mips_cp0sel_names = chosen_arch->cp0sel_names; - mips_cp0sel_names_len = chosen_arch->cp0sel_names_len; - mips_hwr_names = chosen_arch->hwr_names; - } - return; - } - - /* Invalid option. */ -} - -void -parse_mips_dis_options (const char *options) -{ - const char *option_end; - - if (!options) { - return; - } - - while (*options != '\0') - { - /* Skip empty options. */ - if (*options == ',') - { - options++; - continue; - } - - /* We know that *options is neither NUL or a comma. */ - option_end = options + 1; - while (*option_end != ',' && *option_end != '\0') { - option_end++; - } - - parse_mips_dis_option (options, option_end - options); - - /* Go on to the next one. If option_end points to a comma, it - will be skipped above. */ - options = option_end; - } -} - -static const struct mips_cp0sel_name * -lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names, - unsigned int len, - unsigned int cp0reg, - unsigned int sel) -{ - unsigned int i; - - for (i = 0; i < len; i++) { - if (names[i].cp0reg == cp0reg && names[i].sel == sel) { - return &names[i]; - } - } - return NULL; -} - -/* Print insn arguments for 32/64-bit code. */ - -static void -print_insn_args (const char *d, - register unsigned long int l, - bfd_vma pc, - struct disassemble_info *info, - const struct mips_opcode *opp) -{ - int op, delta; - unsigned int lsb, msb, msbd; - - lsb = 0; - - for (; *d != '\0'; d++) - { - switch (*d) - { - case ',': - (*info->fprintf_func) (info->stream, "%c ", *d); - break; - case '(': - case ')': - case '[': - case ']': - (*info->fprintf_func) (info->stream, "%c", *d); - break; - - case '+': - /* Extension character; switch for second char. */ - d++; - switch (*d) - { - case '\0': - /* xgettext:c-format */ - (*info->fprintf_func) (info->stream, - _("# internal error, incomplete extension sequence (+)")); - return; - - case 'A': - lsb = (l >> OP_SH_SHAMT) & OP_MASK_SHAMT; - (*info->fprintf_func) (info->stream, "0x%x", lsb); - break; - - case 'B': - msb = (l >> OP_SH_INSMSB) & OP_MASK_INSMSB; - (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1); - break; - - case '1': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_UDI1) & OP_MASK_UDI1); - break; - - case '2': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_UDI2) & OP_MASK_UDI2); - break; - - case '3': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_UDI3) & OP_MASK_UDI3); - break; - - case '4': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_UDI4) & OP_MASK_UDI4); - break; - - case 'C': - case 'H': - msbd = (l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD; - (*info->fprintf_func) (info->stream, "0x%x", msbd + 1); - break; - - case 'D': - { - const struct mips_cp0sel_name *n; - unsigned int cp0reg, sel; - - cp0reg = (l >> OP_SH_RD) & OP_MASK_RD; - sel = (l >> OP_SH_SEL) & OP_MASK_SEL; - - /* CP0 register including 'sel' code for mtcN (et al.), to be - printed textually if known. If not known, print both - CP0 register name and sel numerically since CP0 register - with sel 0 may have a name unrelated to register being - printed. */ - n = lookup_mips_cp0sel_name(mips_cp0sel_names, - mips_cp0sel_names_len, cp0reg, sel); - if (n != NULL) { - (*info->fprintf_func) (info->stream, "%s", n->name); - } else { - (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel); - } - break; - } - - case 'E': - lsb = ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT) + 32; - (*info->fprintf_func) (info->stream, "0x%x", lsb); - break; - - case 'F': - msb = ((l >> OP_SH_INSMSB) & OP_MASK_INSMSB) + 32; - (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1); - break; - - case 'G': - msbd = ((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD) + 32; - (*info->fprintf_func) (info->stream, "0x%x", msbd + 1); - break; - - case 't': /* Coprocessor 0 reg name */ - (*info->fprintf_func) (info->stream, "%s", - mips_cp0_names[(l >> OP_SH_RT) & - OP_MASK_RT]); - break; - - case 'T': /* Coprocessor 0 reg name */ - { - const struct mips_cp0sel_name *n; - unsigned int cp0reg, sel; - - cp0reg = (l >> OP_SH_RT) & OP_MASK_RT; - sel = (l >> OP_SH_SEL) & OP_MASK_SEL; - - /* CP0 register including 'sel' code for mftc0, to be - printed textually if known. If not known, print both - CP0 register name and sel numerically since CP0 register - with sel 0 may have a name unrelated to register being - printed. */ - n = lookup_mips_cp0sel_name(mips_cp0sel_names, - mips_cp0sel_names_len, cp0reg, sel); - if (n != NULL) { - (*info->fprintf_func) (info->stream, "%s", n->name); - } else { - (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel); - } - break; - } - - default: - /* xgettext:c-format */ - (*info->fprintf_func) (info->stream, - _("# internal error, undefined extension sequence (+%c)"), - *d); - return; - } - break; - - case '2': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_BP) & OP_MASK_BP); - break; - - case '3': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_SA3) & OP_MASK_SA3); - break; - - case '4': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_SA4) & OP_MASK_SA4); - break; - - case '5': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_IMM8) & OP_MASK_IMM8); - break; - - case '6': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_RS) & OP_MASK_RS); - break; - - case '7': - (*info->fprintf_func) (info->stream, "$ac%ld", - (l >> OP_SH_DSPACC) & OP_MASK_DSPACC); - break; - - case '8': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_WRDSP) & OP_MASK_WRDSP); - break; - - case '9': - (*info->fprintf_func) (info->stream, "$ac%ld", - (l >> OP_SH_DSPACC_S) & OP_MASK_DSPACC_S); - break; - - case '0': /* dsp 6-bit signed immediate in bit 20 */ - delta = ((l >> OP_SH_DSPSFT) & OP_MASK_DSPSFT); - if (delta & 0x20) { /* test sign bit */ - delta |= ~OP_MASK_DSPSFT; - } - (*info->fprintf_func) (info->stream, "%d", delta); - break; - - case ':': /* dsp 7-bit signed immediate in bit 19 */ - delta = ((l >> OP_SH_DSPSFT_7) & OP_MASK_DSPSFT_7); - if (delta & 0x40) { /* test sign bit */ - delta |= ~OP_MASK_DSPSFT_7; - } - (*info->fprintf_func) (info->stream, "%d", delta); - break; - - case '\'': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_RDDSP) & OP_MASK_RDDSP); - break; - - case '@': /* dsp 10-bit signed immediate in bit 16 */ - delta = ((l >> OP_SH_IMM10) & OP_MASK_IMM10); - if (delta & 0x200) { /* test sign bit */ - delta |= ~OP_MASK_IMM10; - } - (*info->fprintf_func) (info->stream, "%d", delta); - break; - - case '!': - (*info->fprintf_func) (info->stream, "%ld", - (l >> OP_SH_MT_U) & OP_MASK_MT_U); - break; - - case '$': - (*info->fprintf_func) (info->stream, "%ld", - (l >> OP_SH_MT_H) & OP_MASK_MT_H); - break; - - case '*': - (*info->fprintf_func) (info->stream, "$ac%ld", - (l >> OP_SH_MTACC_T) & OP_MASK_MTACC_T); - break; - - case '&': - (*info->fprintf_func) (info->stream, "$ac%ld", - (l >> OP_SH_MTACC_D) & OP_MASK_MTACC_D); - break; - - case 'g': - /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2. */ - (*info->fprintf_func) (info->stream, "$%ld", - (l >> OP_SH_RD) & OP_MASK_RD); - break; - - case 's': - case 'b': - case 'r': - case 'v': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]); - break; - - case 't': - case 'w': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); - break; - - case 'i': - case 'u': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE); - break; - - case 'j': /* Same as i, but sign-extended. */ - case 'o': - delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; - if (delta & 0x8000) { - delta |= ~0xffff; - } - (*info->fprintf_func) (info->stream, "%d", - delta); - break; - - case 'h': - (*info->fprintf_func) (info->stream, "0x%x", - (unsigned int) ((l >> OP_SH_PREFX) - & OP_MASK_PREFX)); - break; - - case 'k': - (*info->fprintf_func) (info->stream, "0x%x", - (unsigned int) ((l >> OP_SH_CACHE) - & OP_MASK_CACHE)); - break; - - case 'a': - info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff) - | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)); - /* For gdb disassembler, force odd address on jalx. */ - //if (info->flavour == bfd_target_unknown_flavour - // && strcmp (opp->name, "jalx") == 0) - //info->target |= 1; - (*info->print_address_func) (info->target, info); - break; - - case 'p': - /* Sign extend the displacement. */ - delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; - if (delta & 0x8000) { - delta |= ~0xffff; - } - info->target = (delta << 2) + pc + INSNLEN; - (*info->print_address_func) (info->target, info); - break; - - case 'd': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]); - break; - - case 'U': - { - /* First check for both rd and rt being equal. */ - unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD; - if (reg == ((l >> OP_SH_RT) & OP_MASK_RT)) { - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[reg]); - } else { - /* If one is zero use the other. */ - if (reg == 0) { - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); - } else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0) { - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[reg]); - } else { /* Bogus, result depends on processor. */ - (*info->fprintf_func) (info->stream, "%s or %s", - mips_gpr_names[reg], - mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); - } - } - } - break; - - case 'z': - (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]); - break; - - case '<': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_SHAMT) & OP_MASK_SHAMT); - break; - - case 'c': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_CODE) & OP_MASK_CODE); - break; - - case 'q': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_CODE2) & OP_MASK_CODE2); - break; - - case 'C': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_COPZ) & OP_MASK_COPZ); - break; - - case 'B': - (*info->fprintf_func) (info->stream, "0x%lx", - - (l >> OP_SH_CODE20) & OP_MASK_CODE20); - break; - - case 'J': - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_CODE19) & OP_MASK_CODE19); - break; - - case 'S': - case 'V': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]); - break; - - case 'T': - case 'W': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]); - break; - - case 'D': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]); - break; - - case 'R': - (*info->fprintf_func) (info->stream, "%s", - mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]); - break; - - case 'E': - /* Coprocessor register for lwcN instructions, et al. - - Note that there is no load/store cp0 instructions, and - that FPU (cp1) instructions disassemble this field using - 'T' format. Therefore, until we gain understanding of - cp2 register names, we can simply print the register - numbers. */ - (*info->fprintf_func) (info->stream, "$%ld", - (l >> OP_SH_RT) & OP_MASK_RT); - break; - - case 'G': - /* Coprocessor register for mtcN instructions, et al. Note - that FPU (cp1) instructions disassemble this field using - 'S' format. Therefore, we only need to worry about cp0, - cp2, and cp3. */ - op = (l >> OP_SH_OP) & OP_MASK_OP; - if (op == OP_OP_COP0) { - (*info->fprintf_func) (info->stream, "%s", - mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]); - } else { - (*info->fprintf_func) (info->stream, "$%ld", - (l >> OP_SH_RD) & OP_MASK_RD); - } - break; - - case 'K': - (*info->fprintf_func) (info->stream, "%s", - mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]); - break; - - case 'N': - (*info->fprintf_func) (info->stream, - ((opp->pinfo & (FP_D | FP_S)) != 0 - ? "$fcc%ld" : "$cc%ld"), - (l >> OP_SH_BCC) & OP_MASK_BCC); - break; - - case 'M': - (*info->fprintf_func) (info->stream, "$fcc%ld", - (l >> OP_SH_CCC) & OP_MASK_CCC); - break; - - case 'P': - (*info->fprintf_func) (info->stream, "%ld", - (l >> OP_SH_PERFREG) & OP_MASK_PERFREG); - break; - - case 'e': - (*info->fprintf_func) (info->stream, "%ld", - (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE); - break; - - case '%': - (*info->fprintf_func) (info->stream, "%ld", - (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN); - break; - - case 'H': - (*info->fprintf_func) (info->stream, "%ld", - (l >> OP_SH_SEL) & OP_MASK_SEL); - break; - - case 'O': - (*info->fprintf_func) (info->stream, "%ld", - (l >> OP_SH_ALN) & OP_MASK_ALN); - break; - - case 'Q': - { - unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL; - - if ((vsel & 0x10) == 0) - { - int fmt; - - vsel &= 0x0f; - for (fmt = 0; fmt < 3; fmt++, vsel >>= 1) { - if ((vsel & 1) == 0) { - break; - } - } - (*info->fprintf_func) (info->stream, "$v%ld[%d]", - (l >> OP_SH_FT) & OP_MASK_FT, - vsel >> 1); - } - else if ((vsel & 0x08) == 0) - { - (*info->fprintf_func) (info->stream, "$v%ld", - (l >> OP_SH_FT) & OP_MASK_FT); - } - else - { - (*info->fprintf_func) (info->stream, "0x%lx", - (l >> OP_SH_FT) & OP_MASK_FT); - } - } - break; - - case 'X': - (*info->fprintf_func) (info->stream, "$v%ld", - (l >> OP_SH_FD) & OP_MASK_FD); - break; - - case 'Y': - (*info->fprintf_func) (info->stream, "$v%ld", - (l >> OP_SH_FS) & OP_MASK_FS); - break; - - case 'Z': - (*info->fprintf_func) (info->stream, "$v%ld", - (l >> OP_SH_FT) & OP_MASK_FT); - break; - - default: - /* xgettext:c-format */ - (*info->fprintf_func) (info->stream, - _("# internal error, undefined modifier(%c)"), - *d); - return; - } - } -} - -/* Print the mips instruction at address MEMADDR in debugged memory, - on using INFO. Returns length of the instruction, in bytes, which is - always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if - this is little-endian code. */ - -static int -print_insn_mips (bfd_vma memaddr, - unsigned long int word, - struct disassemble_info *info) -{ - const struct mips_opcode *op; - static bfd_boolean init = 0; - static const struct mips_opcode *mips_hash[OP_MASK_OP + 1]; - - /* Build a hash table to shorten the search time. */ - if (! init) - { - unsigned int i; - - for (i = 0; i <= OP_MASK_OP; i++) - { - for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++) - { - if (op->pinfo == INSN_MACRO || (no_aliases && (op->pinfo2 & INSN2_ALIAS))) { - continue; - } - if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) { - mips_hash[i] = op; - break; - } - } - } - - init = 1; - } - - info->bytes_per_chunk = INSNLEN; - info->display_endian = info->endian; - info->insn_info_valid = 1; - info->branch_delay_insns = 0; - info->data_size = 0; - info->insn_type = dis_nonbranch; - info->target = 0; - info->target2 = 0; - - op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP]; - if (op != NULL) - { - for (; op < &mips_opcodes[NUMOPCODES]; op++) - { - if (op->pinfo != INSN_MACRO - && !(no_aliases && (op->pinfo2 & INSN2_ALIAS)) - && (word & op->mask) == op->match) - { - const char *d; - - /* We always allow to disassemble the jalx instruction. */ - if (!OPCODE_IS_MEMBER (op, mips_isa, mips_processor) && strcmp (op->name, "jalx")) { - continue; - } - - /* Figure out instruction type and branch delay information. */ - if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0) - { - if ((info->insn_type & INSN_WRITE_GPR_31) != 0) { - info->insn_type = dis_jsr; - } else { - info->insn_type = dis_branch; - } - info->branch_delay_insns = 1; - } - else if ((op->pinfo & (INSN_COND_BRANCH_DELAY - | INSN_COND_BRANCH_LIKELY)) != 0) - { - if ((info->insn_type & INSN_WRITE_GPR_31) != 0) { - info->insn_type = dis_condjsr; - } else { - info->insn_type = dis_condbranch; - } - info->branch_delay_insns = 1; - } else if ((op->pinfo & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY_DELAY)) != 0) { - info->insn_type = dis_dref; - } - - (*info->fprintf_func) (info->stream, "%s", op->name); - - d = op->args; - if (d != NULL && *d != '\0') { - (*info->fprintf_func) (info->stream, " "); - print_insn_args (d, word, memaddr, info, op); - } - - return INSNLEN; - } - } - } - - /* Plugin undefined instructions. */ - info->insn_type = dis_noninsn; - (*info->fprintf_func) (info->stream, "0x%lx", word); - return INSNLEN; -} - -/* Disassemble an operand for a mips16 instruction. */ - -static void -print_mips16_insn_arg (char type, - const struct mips_opcode *op, - int l, - bfd_boolean use_extend, - int extend, - bfd_vma memaddr, - struct disassemble_info *info) -{ - switch (type) - { - case ',': - case '(': - case ')': - (*info->fprintf_func) (info->stream, "%c", type); - break; - - case 'y': - case 'w': - (*info->fprintf_func) (info->stream, "%s", - mips16_reg_names(((l >> MIPS16OP_SH_RY) - & MIPS16OP_MASK_RY))); - break; - - case 'x': - case 'v': - (*info->fprintf_func) (info->stream, "%s", - mips16_reg_names(((l >> MIPS16OP_SH_RX) - & MIPS16OP_MASK_RX))); - break; - - case 'z': - (*info->fprintf_func) (info->stream, "%s", - mips16_reg_names(((l >> MIPS16OP_SH_RZ) - & MIPS16OP_MASK_RZ))); - break; - - case 'Z': - (*info->fprintf_func) (info->stream, "%s", - mips16_reg_names(((l >> MIPS16OP_SH_MOVE32Z) - & MIPS16OP_MASK_MOVE32Z))); - break; - - case '0': - (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]); - break; - - case 'S': - (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[29]); - break; - - case 'P': - (*info->fprintf_func) (info->stream, "$pc"); - break; - - case 'R': - (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[31]); - break; - - case 'X': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[((l >> MIPS16OP_SH_REGR32) - & MIPS16OP_MASK_REGR32)]); - break; - - case 'Y': - (*info->fprintf_func) (info->stream, "%s", - mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]); - break; - - case '<': - case '>': - case '[': - case ']': - case '4': - case '5': - case 'H': - case 'W': - case 'D': - case 'j': - case '6': - case '8': - case 'V': - case 'C': - case 'U': - case 'k': - case 'K': - case 'p': - case 'q': - case 'A': - case 'B': - case 'E': - { - int immed, nbits, shift, signedp, extbits, pcrel, extu, branch; - - shift = 0; - signedp = 0; - extbits = 16; - pcrel = 0; - extu = 0; - branch = 0; - switch (type) - { - case '<': - nbits = 3; - immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ; - extbits = 5; - extu = 1; - break; - case '>': - nbits = 3; - immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX; - extbits = 5; - extu = 1; - break; - case '[': - nbits = 3; - immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ; - extbits = 6; - extu = 1; - break; - case ']': - nbits = 3; - immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX; - extbits = 6; - extu = 1; - break; - case '4': - nbits = 4; - immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4; - signedp = 1; - extbits = 15; - break; - case '5': - nbits = 5; - immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5; - info->insn_type = dis_dref; - info->data_size = 1; - break; - case 'H': - nbits = 5; - shift = 1; - immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5; - info->insn_type = dis_dref; - info->data_size = 2; - break; - case 'W': - nbits = 5; - shift = 2; - immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5; - if ((op->pinfo & MIPS16_INSN_READ_PC) == 0 - && (op->pinfo & MIPS16_INSN_READ_SP) == 0) - { - info->insn_type = dis_dref; - info->data_size = 4; - } - break; - case 'D': - nbits = 5; - shift = 3; - immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5; - info->insn_type = dis_dref; - info->data_size = 8; - break; - case 'j': - nbits = 5; - immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5; - signedp = 1; - break; - case '6': - nbits = 6; - immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6; - break; - case '8': - nbits = 8; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - break; - case 'V': - nbits = 8; - shift = 2; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - /* FIXME: This might be lw, or it might be addiu to $sp or - $pc. We assume it's load. */ - info->insn_type = dis_dref; - info->data_size = 4; - break; - case 'C': - nbits = 8; - shift = 3; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - info->insn_type = dis_dref; - info->data_size = 8; - break; - case 'U': - nbits = 8; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - extu = 1; - break; - case 'k': - nbits = 8; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - signedp = 1; - break; - case 'K': - nbits = 8; - shift = 3; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - signedp = 1; - break; - case 'p': - nbits = 8; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - signedp = 1; - pcrel = 1; - branch = 1; - info->insn_type = dis_condbranch; - break; - case 'q': - nbits = 11; - immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11; - signedp = 1; - pcrel = 1; - branch = 1; - info->insn_type = dis_branch; - break; - case 'A': - nbits = 8; - shift = 2; - immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8; - pcrel = 1; - /* FIXME: This can be lw or la. We assume it is lw. */ - info->insn_type = dis_dref; - info->data_size = 4; - break; - case 'B': - nbits = 5; - shift = 3; - immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5; - pcrel = 1; - info->insn_type = dis_dref; - info->data_size = 8; - break; - case 'E': - nbits = 5; - shift = 2; - immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5; - pcrel = 1; - break; - default: - abort (); - } - - if (! use_extend) - { - if (signedp && immed >= (1 << (nbits - 1))) { - immed -= 1 << nbits; - } - immed <<= shift; - if ((type == '<' || type == '>' || type == '[' || type == ']') && immed == 0) { - immed = 8; - } - } - else - { - if (extbits == 16) { - immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0); - } else if (extbits == 15) { - immed |= ((extend & 0xf) << 11) | (extend & 0x7f0); - } else { - immed = ((extend >> 6) & 0x1f) | (extend & 0x20); - } - immed &= (1 << extbits) - 1; - if (!extu && immed >= (1 << (extbits - 1))) { - immed -= 1 << extbits; - } - } - - if (!pcrel) { - (*info->fprintf_func) (info->stream, "%d", immed); - } else { - bfd_vma baseaddr; - - if (branch) { - immed *= 2; - baseaddr = memaddr + 2; - } else if (use_extend) { - baseaddr = memaddr - 2; - } else { - int status; - bfd_byte buffer[2]; - - baseaddr = memaddr; - - /* If this instruction is in the delay slot of a jr - instruction, the base address is the address of the - jr instruction. If it is in the delay slot of jalr - instruction, the base address is the address of the - jalr instruction. This test is unreliable: we have - no way of knowing whether the previous word is - instruction or data. */ - status = (*info->read_memory_func) (memaddr - 4, buffer, 2, - info); - if (status == 0 && (((info->endian == BFD_ENDIAN_BIG - ? bfd_getb16 (buffer) - : bfd_getl16 (buffer)) & - 0xf800) == 0x1800)) { - baseaddr = memaddr - 4; - } else { - status = (*info->read_memory_func) (memaddr - 2, buffer, - 2, info); - if (status == 0 && (((info->endian == BFD_ENDIAN_BIG - ? bfd_getb16 (buffer) - : bfd_getl16 (buffer)) & - 0xf81f) == 0xe800)) { - baseaddr = memaddr - 2; - } - } - } - info->target = (baseaddr & ~((1 << shift) - 1)) + immed; - if (pcrel && branch && info->flavour == bfd_target_unknown_flavour) { - /* For gdb disassembler, maintain odd address. */ - info->target |= 1; - } - (*info->print_address_func) (info->target, info); - } - } - break; - - case 'a': - { - int jalx = l & 0x400; - - if (!use_extend) { - extend = 0; - } - l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2); - if (!jalx && info->flavour == bfd_target_unknown_flavour) { - /* For gdb disassembler, maintain odd address. */ - l |= 1; - } - } - info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l; - (*info->print_address_func) (info->target, info); - info->insn_type = dis_jsr; - info->branch_delay_insns = 1; - break; - - case 'l': - case 'L': - { - int need_comma, amask, smask; - - need_comma = 0; - - l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6; - - amask = (l >> 3) & 7; - - if (amask > 0 && amask < 5) - { - (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]); - if (amask > 1) { - (*info->fprintf_func) (info->stream, "-%s", - mips_gpr_names[amask + 3]); - } - need_comma = 1; - } - - smask = (l >> 1) & 3; - if (smask == 3) - { - (*info->fprintf_func) (info->stream, "%s??", - need_comma ? ", " : ""); - need_comma = 1; - } - else if (smask > 0) - { - (*info->fprintf_func) (info->stream, "%s%s", - need_comma ? ", " : "", - mips_gpr_names[16]); - if (smask > 1) { - (*info->fprintf_func) (info->stream, "-%s", - mips_gpr_names[smask + 15]); - } - need_comma = 1; - } - - if (l & 1) - { - (*info->fprintf_func) (info->stream, "%s%s", - need_comma ? ", " : "", - mips_gpr_names[31]); - need_comma = 1; - } - - if (amask == 5 || amask == 6) - { - (*info->fprintf_func) (info->stream, "%s$f0", - need_comma ? ", " : ""); - if (amask == 6) { - (*info->fprintf_func) (info->stream, "-$f1"); - } - } - } - break; - - case 'm': - case 'M': - /* MIPS16e save/restore. */ - { - int need_comma = 0; - int amask, args, statics; - int nsreg, smask; - int framesz; - int i, j; - - l = l & 0x7f; - if (use_extend) { - l |= extend << 16; - } - - amask = (l >> 16) & 0xf; - if (amask == MIPS16_ALL_ARGS) - { - args = 4; - statics = 0; - } - else if (amask == MIPS16_ALL_STATICS) - { - args = 0; - statics = 4; - } - else - { - args = amask >> 2; - statics = amask & 3; - } - - if (args > 0) { - (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]); - if (args > 1) { - (*info->fprintf_func) (info->stream, "-%s", - mips_gpr_names[4 + args - 1]); - } - need_comma = 1; - } - - framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8; - if (framesz == 0 && !use_extend) { - framesz = 128; - } - - (*info->fprintf_func) (info->stream, "%s%d", - need_comma ? ", " : "", - framesz); - - if (l & 0x40) { /* $ra */ - (*info->fprintf_func) (info->stream, ", %s", mips_gpr_names[31]); - } - - nsreg = (l >> 24) & 0x7; - smask = 0; - if (l & 0x20) { /* $s0 */ - smask |= 1 << 0; - } - if (l & 0x10) { /* $s1 */ - smask |= 1 << 1; - } - if (nsreg > 0) { /* $s2-$s8 */ - smask |= ((1 << nsreg) - 1) << 2; - } - - /* Find first set static reg bit. */ - for (i = 0; i < 9; i++) - { - if (smask & (1 << i)) - { - (*info->fprintf_func) (info->stream, ", %s", - mips_gpr_names[i == 8 ? 30 : (16 + i)]); - /* Skip over string of set bits. */ - for (j = i; smask & (2 << j); j++) {} - if (j > i) { - (*info->fprintf_func) (info->stream, "-%s", - mips_gpr_names[j == 8 ? 30 : (16 + j)]); - } - i = j + 1; - } - } - - /* Statics $ax - $a3. */ - if (statics == 1) { - (*info->fprintf_func) (info->stream, ", %s", mips_gpr_names[7]); - } else if (statics > 0) { - (*info->fprintf_func) (info->stream, ", %s-%s", - mips_gpr_names[7 - statics + 1], - mips_gpr_names[7]); - } - } - break; - - default: - /* xgettext:c-format */ - (*info->fprintf_func) - (info->stream, - _("# internal disassembler error, unrecognised modifier (%c)"), - type); - abort (); - } -} - -/* Disassemble mips16 instructions. */ - -static int -print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info) -{ - int status; - bfd_byte buffer[2]; - int length; - int insn; - bfd_boolean use_extend; - int extend = 0; - const struct mips_opcode *op, *opend; - - info->bytes_per_chunk = 2; - info->display_endian = info->endian; - info->insn_info_valid = 1; - info->branch_delay_insns = 0; - info->data_size = 0; - info->insn_type = dis_nonbranch; - info->target = 0; - info->target2 = 0; - - status = (*info->read_memory_func) (memaddr, buffer, 2, info); - if (status != 0) - { - (*info->memory_error_func) (status, memaddr, info); - return -1; - } - - length = 2; - - if (info->endian == BFD_ENDIAN_BIG) { - insn = bfd_getb16 (buffer); - } else { - insn = bfd_getl16 (buffer); - } - - /* Plugin the extend opcode specially. */ - use_extend = FALSE; - if ((insn & 0xf800) == 0xf000) - { - use_extend = TRUE; - extend = insn & 0x7ff; - - memaddr += 2; - - status = (*info->read_memory_func) (memaddr, buffer, 2, info); - if (status != 0) - { - (*info->fprintf_func) (info->stream, "extend 0x%x", - (unsigned int) extend); - (*info->memory_error_func) (status, memaddr, info); - return -1; - } - - if (info->endian == BFD_ENDIAN_BIG) { - insn = bfd_getb16 (buffer); - } else { - insn = bfd_getl16 (buffer); - } - - /* Check for an extend opcode followed by an extend opcode. */ - if ((insn & 0xf800) == 0xf000) { - (*info->fprintf_func) (info->stream, "extend 0x%x", - (unsigned int)extend); - info->insn_type = dis_noninsn; - return length; - } - - length += 2; - } - - /* FIXME: Should probably use a hash table on the major opcode here. */ - - opend = mips16_opcodes + bfd_mips16_num_opcodes; - for (op = mips16_opcodes; op < opend; op++) - { - if (op->pinfo != INSN_MACRO - && !(no_aliases && (op->pinfo2 & INSN2_ALIAS)) - && (insn & op->mask) == op->match) - { - const char *s; - - if (strchr (op->args, 'a') != NULL) - { - if (use_extend) - { - (*info->fprintf_func) (info->stream, "extend 0x%x", - (unsigned int) extend); - info->insn_type = dis_noninsn; - return length - 2; - } - - use_extend = FALSE; - - memaddr += 2; - - status = (*info->read_memory_func) (memaddr, buffer, 2, - info); - if (status == 0) - { - use_extend = TRUE; - if (info->endian == BFD_ENDIAN_BIG) { - extend = bfd_getb16 (buffer); - } else { - extend = bfd_getl16 (buffer); - } - length += 2; - } - } - - (*info->fprintf_func) (info->stream, "%s", op->name); - if (op->args[0] != '\0') { - (*info->fprintf_func) (info->stream, " "); - } - - for (s = op->args; *s != '\0'; s++) - { - if (*s == ',' - && s[1] == 'w' - && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX) - == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY))) - { - /* Skip the register and the comma. */ - ++s; - continue; - } - if (*s == ',' - && s[1] == 'v' - && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ) - == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX))) - { - /* Skip the register and the comma. */ - ++s; - continue; - } - print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr, - info); - } - - if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0) - { - info->branch_delay_insns = 1; - if (info->insn_type != dis_jsr) { - info->insn_type = dis_branch; - } - } - - return length; - } - } - - if (use_extend) { - (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000); - } - (*info->fprintf_func) (info->stream, "0x%x", insn); - info->insn_type = dis_noninsn; - - return length; -} - -/* In an environment where we do not know the symbol type of the - instruction we are forced to assume that the low order bit of the - instructions' address may mark it as a mips16 instruction. If we - are single stepping, or the pc is within the disassembled function, - this works. Otherwise, we need a clue. Sometimes. */ - -static int -_print_insn_mips (bfd_vma memaddr, - struct disassemble_info *info, - enum bfd_endian endianness) -{ - bfd_byte buffer[INSNLEN]; - int status; - - set_default_mips_dis_options (info); - parse_mips_dis_options (info->disassembler_options); - -#if 1 - /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */ - /* Only a few tools will work this way. */ - if (memaddr & 0x01) { - return print_insn_mips16 (memaddr, info); - } -#endif - -#if SYMTAB_AVAILABLE - if (info->mach == bfd_mach_mips16 || (info->flavour == bfd_target_elf_flavour && info->symbols != NULL && ((*(elf_symbol_type **)info->symbols)->internal_elf_sym.st_other == STO_MIPS16))) { - return print_insn_mips16 (memaddr, info); - } -#endif - - status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info); - if (status == 0) - { - unsigned long insn; - - if (endianness == BFD_ENDIAN_BIG) { - insn = (unsigned long)bfd_getb32 (buffer); - } else { - insn = (unsigned long)bfd_getl32 (buffer); - } - - return print_insn_mips (memaddr, insn, info); - } - else - { - (*info->memory_error_func) (status, memaddr, info); - return -1; - } -} - -int -print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info) -{ - return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG); -} - -int -print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info) -{ - return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE); -} - -void -print_mips_disassembler_options (FILE *stream) -{ - unsigned int i; - - fprintf (stream, _("\n\ -The following MIPS specific disassembler options are supported for use\n\ -with the -M switch (multiple options should be separated by commas):\n")); - - fprintf (stream, _("\n\ - gpr-names=ABI Print GPR names according to specified ABI.\n\ - Default: based on binary being disassembled.\n")); - - fprintf (stream, _("\n\ - fpr-names=ABI Print FPR names according to specified ABI.\n\ - Default: numeric.\n")); - - fprintf (stream, _("\n\ - cp0-names=ARCH Print CP0 register names according to\n\ - specified architecture.\n\ - Default: based on binary being disassembled.\n")); - - fprintf (stream, _("\n\ - hwr-names=ARCH Print HWR names according to specified \n\ - architecture.\n\ - Default: based on binary being disassembled.\n")); - - fprintf (stream, _("\n\ - reg-names=ABI Print GPR and FPR names according to\n\ - specified ABI.\n")); - - fprintf (stream, _("\n\ - reg-names=ARCH Print CP0 register and HWR names according to\n\ - specified architecture.\n")); - - fprintf (stream, _("\n\ - For the options above, the following values are supported for \"ABI\":\n\ - ")); - for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++) { - fprintf (stream, " %s", mips_abi_choices[i].name); - } - fprintf (stream, _("\n")); - - fprintf (stream, _("\n\ - For the options above, The following values are supported for \"ARCH\":\n\ - ")); - for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++) { - if (*mips_arch_choices[i].name != '\0') { - fprintf (stream, " %s", mips_arch_choices[i].name); - } - } - fprintf (stream, _("\n")); - - fprintf (stream, _("\n")); -} diff --git a/librz/arch/isa_gnu/mips/mips-opc.c b/librz/arch/isa_gnu/mips/mips-opc.c deleted file mode 100644 index 9161652e4ce..00000000000 --- a/librz/arch/isa_gnu/mips/mips-opc.c +++ /dev/null @@ -1,2018 +0,0 @@ -/* mips-opc.c -- MIPS opcode list. - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 - 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. - Contributed by Ralph Campbell and OSF - Commented and modified by Ian Lance Taylor, Cygnus Support - Extended for MIPS32 support by Anders Norlander, and by SiByte, Inc. - MIPS-3D, MDMX, and MIPS32 Release 2 support added by Broadcom - Corporation (SiByte). - - This file is part of the GNU opcodes library. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - It is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with this file; see the file COPYING. If not, write to the - Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, - MA 02110-1301, USA. */ - -#include -#include -#include - -/* Short hand so the lines aren't too long. */ - -#define LDD INSN_LOAD_MEMORY_DELAY -#define LCD INSN_LOAD_COPROC_DELAY -#define UBD INSN_UNCOND_BRANCH_DELAY -#define CBD INSN_COND_BRANCH_DELAY -#define COD INSN_COPROC_MOVE_DELAY -#define CLD INSN_COPROC_MEMORY_DELAY -#define CBL INSN_COND_BRANCH_LIKELY -#define TRAP INSN_TRAP -#define SM INSN_STORE_MEMORY - -#define WR_d INSN_WRITE_GPR_D -#define WR_t INSN_WRITE_GPR_T -#define WR_31 INSN_WRITE_GPR_31 -#define WR_D INSN_WRITE_FPR_D -#define WR_T INSN_WRITE_FPR_T -#define WR_S INSN_WRITE_FPR_S -#define RD_s INSN_READ_GPR_S -#define RD_b INSN_READ_GPR_S -#define RD_t INSN_READ_GPR_T -#define RD_S INSN_READ_FPR_S -#define RD_T INSN_READ_FPR_T -#define RD_R INSN_READ_FPR_R -#define WR_CC INSN_WRITE_COND_CODE -#define RD_CC INSN_READ_COND_CODE -#define RD_C0 INSN_COP -#define RD_C1 INSN_COP -#define RD_C2 INSN_COP -#define RD_C3 INSN_COP -#define WR_C0 INSN_COP -#define WR_C1 INSN_COP -#define WR_C2 INSN_COP -#define WR_C3 INSN_COP - -#define WR_HI INSN_WRITE_HI -#define RD_HI INSN_READ_HI -#define MOD_HI (WR_HI|RD_HI) - -#define WR_LO INSN_WRITE_LO -#define RD_LO INSN_READ_LO -#define MOD_LO (WR_LO|RD_LO) - -#define WR_HILO (WR_HI|WR_LO) -#define RD_HILO (RD_HI|RD_LO) -#define MOD_HILO (WR_HILO|RD_HILO) - -#define IS_M INSN_MULT - -#define WR_MACC INSN2_WRITE_MDMX_ACC -#define RD_MACC INSN2_READ_MDMX_ACC - -#define I1 INSN_ISA1 -#define I2 INSN_ISA2 -#define I3 INSN_ISA3 -#define I4 INSN_ISA4 -#define I5 INSN_ISA5 -#define I32 INSN_ISA32 -#define I64 INSN_ISA64 -#define I33 INSN_ISA32R2 -#define I65 INSN_ISA64R2 -#define I3_32 INSN_ISA3_32 -#define I3_33 INSN_ISA3_32R2 -#define I4_32 INSN_ISA4_32 -#define I4_33 INSN_ISA4_32R2 -#define I5_33 INSN_ISA5_32R2 - -/* MIPS16 ASE support. */ -#define I16 INSN_MIPS16 - -/* MIPS64 MIPS-3D ASE support. */ -#define M3D INSN_MIPS3D - -/* MIPS32 SmartMIPS ASE support. */ -#define SMT INSN_SMARTMIPS - -/* MIPS64 MDMX ASE support. */ -#define MX INSN_MDMX - -#define IL2E (INSN_LOONGSON_2E) -#define IL2F (INSN_LOONGSON_2F) - -#define P3 INSN_4650 -#define L1 INSN_4010 -#define V1 (INSN_4100 | INSN_4111 | INSN_4120) -#define T3 INSN_3900 -#define M1 INSN_10000 -#define SB1 INSN_SB1 -#define N411 INSN_4111 -#define N412 INSN_4120 -#define N5 (INSN_5400 | INSN_5500) -#define N54 INSN_5400 -#define N55 INSN_5500 -#define IOCT INSN_OCTEON - -#define G1 (T3 \ - ) - -#define G2 (T3 \ - ) - -#define G3 (I4 \ - ) - -/* MIPS DSP ASE support. - NOTE: - 1. MIPS DSP ASE includes 4 accumulators ($ac0 - $ac3). $ac0 is the pair - of original HI and LO. $ac1, $ac2 and $ac3 are new registers, and have - the same structure as $ac0 (HI + LO). For DSP instructions that write or - read accumulators (that may be $ac0), we add WR_a (WR_HILO) or RD_a - (RD_HILO) attributes, such that HILO dependencies are maintained - conservatively. - - 2. For some mul. instructions that use integer registers as destinations - but destroy HI+LO as side-effect, we add WR_HILO to their attributes. - - 3. MIPS DSP ASE includes a new DSP control register, which has 6 fields - (ccond, outflag, EFI, c, scount, pos). Many DSP instructions read or write - certain fields of the DSP control register. For simplicity, we decide not - to track dependencies of these fields. - However, "bposge32" is a branch instruction that depends on the "pos" - field. In order to make sure that GAS does not reorder DSP instructions - that writes the "pos" field and "bposge32", we add DSP_VOLA (INSN_TRAP) - attribute to those instructions that write the "pos" field. */ - -#define WR_a WR_HILO /* Write dsp accumulators (reuse WR_HILO) */ -#define RD_a RD_HILO /* Read dsp accumulators (reuse RD_HILO) */ -#define MOD_a (WR_a|RD_a) -#define DSP_VOLA INSN_TRAP -#define D32 INSN_DSP -#define D33 INSN_DSPR2 -#define D64 INSN_DSP64 - -/* MIPS MT ASE support. */ -#define MT32 INSN_MT - -/* The order of overloaded instructions matters. Label arguments and - register arguments look the same. Instructions that can have either - for arguments must apear in the correct order in this table for the - assembler to pick the right one. In other words, entries with - immediate operands must apear after the same instruction with - registers. - - Because of the lookup algorithm used, entries with the same opcode - name must be contiguous. - - Many instructions are short hand for other instructions (i.e., The - jal instruction is short for jalr ). */ - -const struct mips_opcode mips_builtin_opcodes[] = -{ -/* These instructions appear first so that the disassembler will find - them first. The assemblers uses a hash table based on the - instruction name anyhow. */ -/* name, args, match, mask, pinfo, pinfo2, membership */ -{"pref", "k,o(b)", 0xcc000000, 0xfc000000, RD_b, 0, I4_32|G3 }, -{"prefx", "h,t(b)", 0x4c00000f, 0xfc0007ff, RD_b|RD_t, 0, I4_33 }, -{"nop", "", 0x00000000, 0xffffffff, 0, INSN2_ALIAS, I1 }, /* sll */ -{"ssnop", "", 0x00000040, 0xffffffff, 0, INSN2_ALIAS, I32|N55 }, /* sll */ -{"ehb", "", 0x000000c0, 0xffffffff, 0, INSN2_ALIAS, I33 }, /* sll */ -{"li", "t,j", 0x24000000, 0xffe00000, WR_t, INSN2_ALIAS, I1 }, /* addiu */ -{"li", "t,i", 0x34000000, 0xffe00000, WR_t, INSN2_ALIAS, I1 }, /* ori */ -{"li", "t,I", 0, (int) M_LI, INSN_MACRO, 0, I1 }, -{"move", "d,s", 0, (int) M_MOVE, INSN_MACRO, 0, I1 }, -{"move", "d,s", 0x0000002d, 0xfc1f07ff, WR_d|RD_s, INSN2_ALIAS, I3 },/* daddu */ -{"move", "d,s", 0x00000021, 0xfc1f07ff, WR_d|RD_s, INSN2_ALIAS, I1 },/* addu */ -{"move", "d,s", 0x00000025, 0xfc1f07ff, WR_d|RD_s, INSN2_ALIAS, I1 },/* or */ -{"b", "p", 0x10000000, 0xffff0000, UBD, INSN2_ALIAS, I1 },/* beq 0,0 */ -{"b", "p", 0x04010000, 0xffff0000, UBD, INSN2_ALIAS, I1 },/* bgez 0 */ -{"bal", "p", 0x04110000, 0xffff0000, UBD|WR_31, INSN2_ALIAS, I1 },/* bgezal 0*/ - -{"abs", "d,v", 0, (int) M_ABS, INSN_MACRO, 0, I1 }, -{"abs.s", "D,V", 0x46000005, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, -{"abs.d", "D,V", 0x46200005, 0xffff003f, WR_D|RD_S|FP_D, 0, I1 }, -{"abs.ps", "D,V", 0x46c00005, 0xffff003f, WR_D|RD_S|FP_D, 0, I5_33|IL2F }, -{"abs.ps", "D,V", 0x45600005, 0xffff003f, WR_D|RD_S|FP_D, 0, IL2E }, -{"add", "d,v,t", 0x00000020, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"add", "t,r,I", 0, (int) M_ADD_I, INSN_MACRO, 0, I1 }, -{"add", "D,S,T", 0x45c00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"add", "D,S,T", 0x4b40000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"add.s", "D,V,T", 0x46000000, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, -{"add.d", "D,V,T", 0x46200000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, -{"add.ob", "X,Y,Q", 0x7800000b, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"add.ob", "D,S,T", 0x4ac0000b, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"add.ob", "D,S,T[e]", 0x4800000b, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"add.ob", "D,S,k", 0x4bc0000b, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"add.ps", "D,V,T", 0x46c00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33|IL2F }, -{"add.ps", "D,V,T", 0x45600000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"add.qh", "X,Y,Q", 0x7820000b, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"adda.ob", "Y,Q", 0x78000037, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"adda.qh", "Y,Q", 0x78200037, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"addi", "t,r,j", 0x20000000, 0xfc000000, WR_t|RD_s, 0, I1 }, -{"addiu", "t,r,j", 0x24000000, 0xfc000000, WR_t|RD_s, 0, I1 }, -{"addl.ob", "Y,Q", 0x78000437, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"addl.qh", "Y,Q", 0x78200437, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"addr.ps", "D,S,T", 0x46c00018, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, -{"addu", "d,v,t", 0x00000021, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"addu", "t,r,I", 0, (int) M_ADDU_I, INSN_MACRO, 0, I1 }, -{"addu", "D,S,T", 0x45800000, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"addu", "D,S,T", 0x4b00000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"alni.ob", "X,Y,Z,O", 0x78000018, 0xff00003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"alni.ob", "D,S,T,%", 0x48000018, 0xff00003f, WR_D|RD_S|RD_T, 0, N54 }, -{"alni.qh", "X,Y,Z,O", 0x7800001a, 0xff00003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"alnv.ps", "D,V,T,s", 0x4c00001e, 0xfc00003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33 }, -{"alnv.ob", "X,Y,Z,s", 0x78000019, 0xfc00003f, WR_D|RD_S|RD_T|RD_s|FP_D, 0, MX|SB1 }, -{"alnv.qh", "X,Y,Z,s", 0x7800001b, 0xfc00003f, WR_D|RD_S|RD_T|RD_s|FP_D, 0, MX }, -{"and", "d,v,t", 0x00000024, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"and", "t,r,I", 0, (int) M_AND_I, INSN_MACRO, 0, I1 }, -{"and", "D,S,T", 0x47c00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"and", "D,S,T", 0x4bc00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"and.ob", "X,Y,Q", 0x7800000c, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"and.ob", "D,S,T", 0x4ac0000c, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"and.ob", "D,S,T[e]", 0x4800000c, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"and.ob", "D,S,k", 0x4bc0000c, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"and.qh", "X,Y,Q", 0x7820000c, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"andi", "t,r,i", 0x30000000, 0xfc000000, WR_t|RD_s, 0, I1 }, -/* b is at the top of the table. */ -/* bal is at the top of the table. */ -/* bc0[tf]l? are at the bottom of the table. */ -{"bc1any2f", "N,p", 0x45200000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, -{"bc1any2t", "N,p", 0x45210000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, -{"bc1any4f", "N,p", 0x45400000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, -{"bc1any4t", "N,p", 0x45410000, 0xffe30000, CBD|RD_CC|FP_S, 0, M3D }, -{"bc1f", "p", 0x45000000, 0xffff0000, CBD|RD_CC|FP_S, 0, I1 }, -{"bc1f", "N,p", 0x45000000, 0xffe30000, CBD|RD_CC|FP_S, 0, I4_32 }, -{"bc1fl", "p", 0x45020000, 0xffff0000, CBL|RD_CC|FP_S, 0, I2|T3 }, -{"bc1fl", "N,p", 0x45020000, 0xffe30000, CBL|RD_CC|FP_S, 0, I4_32 }, -{"bc1t", "p", 0x45010000, 0xffff0000, CBD|RD_CC|FP_S, 0, I1 }, -{"bc1t", "N,p", 0x45010000, 0xffe30000, CBD|RD_CC|FP_S, 0, I4_32 }, -{"bc1tl", "p", 0x45030000, 0xffff0000, CBL|RD_CC|FP_S, 0, I2|T3 }, -{"bc1tl", "N,p", 0x45030000, 0xffe30000, CBL|RD_CC|FP_S, 0, I4_32 }, -/* bc2* are at the bottom of the table. */ -/* bc3* are at the bottom of the table. */ -{"beqz", "s,p", 0x10000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, -{"beqzl", "s,p", 0x50000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, -{"beq", "s,t,p", 0x10000000, 0xfc000000, CBD|RD_s|RD_t, 0, I1 }, -{"beq", "s,I,p", 0, (int) M_BEQ_I, INSN_MACRO, 0, I1 }, -{"beql", "s,t,p", 0x50000000, 0xfc000000, CBL|RD_s|RD_t, 0, I2|T3 }, -{"beql", "s,I,p", 0, (int) M_BEQL_I, INSN_MACRO, 0, I2|T3 }, -{"bge", "s,t,p", 0, (int) M_BGE, INSN_MACRO, 0, I1 }, -{"bge", "s,I,p", 0, (int) M_BGE_I, INSN_MACRO, 0, I1 }, -{"bgel", "s,t,p", 0, (int) M_BGEL, INSN_MACRO, 0, I2|T3 }, -{"bgel", "s,I,p", 0, (int) M_BGEL_I, INSN_MACRO, 0, I2|T3 }, -{"bgeu", "s,t,p", 0, (int) M_BGEU, INSN_MACRO, 0, I1 }, -{"bgeu", "s,I,p", 0, (int) M_BGEU_I, INSN_MACRO, 0, I1 }, -{"bgeul", "s,t,p", 0, (int) M_BGEUL, INSN_MACRO, 0, I2|T3 }, -{"bgeul", "s,I,p", 0, (int) M_BGEUL_I, INSN_MACRO, 0, I2|T3 }, -{"bgez", "s,p", 0x04010000, 0xfc1f0000, CBD|RD_s, 0, I1 }, -{"bgezl", "s,p", 0x04030000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, -{"bgezal", "s,p", 0x04110000, 0xfc1f0000, CBD|RD_s|WR_31, 0, I1 }, -{"bgezall", "s,p", 0x04130000, 0xfc1f0000, CBL|RD_s|WR_31, 0, I2|T3 }, -{"bgt", "s,t,p", 0, (int) M_BGT, INSN_MACRO, 0, I1 }, -{"bgt", "s,I,p", 0, (int) M_BGT_I, INSN_MACRO, 0, I1 }, -{"bgtl", "s,t,p", 0, (int) M_BGTL, INSN_MACRO, 0, I2|T3 }, -{"bgtl", "s,I,p", 0, (int) M_BGTL_I, INSN_MACRO, 0, I2|T3 }, -{"bgtu", "s,t,p", 0, (int) M_BGTU, INSN_MACRO, 0, I1 }, -{"bgtu", "s,I,p", 0, (int) M_BGTU_I, INSN_MACRO, 0, I1 }, -{"bgtul", "s,t,p", 0, (int) M_BGTUL, INSN_MACRO, 0, I2|T3 }, -{"bgtul", "s,I,p", 0, (int) M_BGTUL_I, INSN_MACRO, 0, I2|T3 }, -{"bgtz", "s,p", 0x1c000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, -{"bgtzl", "s,p", 0x5c000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, -{"ble", "s,t,p", 0, (int) M_BLE, INSN_MACRO, 0, I1 }, -{"ble", "s,I,p", 0, (int) M_BLE_I, INSN_MACRO, 0, I1 }, -{"blel", "s,t,p", 0, (int) M_BLEL, INSN_MACRO, 0, I2|T3 }, -{"blel", "s,I,p", 0, (int) M_BLEL_I, INSN_MACRO, 0, I2|T3 }, -{"bleu", "s,t,p", 0, (int) M_BLEU, INSN_MACRO, 0, I1 }, -{"bleu", "s,I,p", 0, (int) M_BLEU_I, INSN_MACRO, 0, I1 }, -{"bleul", "s,t,p", 0, (int) M_BLEUL, INSN_MACRO, 0, I2|T3 }, -{"bleul", "s,I,p", 0, (int) M_BLEUL_I, INSN_MACRO, 0, I2|T3 }, -{"blez", "s,p", 0x18000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, -{"blezl", "s,p", 0x58000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, -{"blt", "s,t,p", 0, (int) M_BLT, INSN_MACRO, 0, I1 }, -{"blt", "s,I,p", 0, (int) M_BLT_I, INSN_MACRO, 0, I1 }, -{"bltl", "s,t,p", 0, (int) M_BLTL, INSN_MACRO, 0, I2|T3 }, -{"bltl", "s,I,p", 0, (int) M_BLTL_I, INSN_MACRO, 0, I2|T3 }, -{"bltu", "s,t,p", 0, (int) M_BLTU, INSN_MACRO, 0, I1 }, -{"bltu", "s,I,p", 0, (int) M_BLTU_I, INSN_MACRO, 0, I1 }, -{"bltul", "s,t,p", 0, (int) M_BLTUL, INSN_MACRO, 0, I2|T3 }, -{"bltul", "s,I,p", 0, (int) M_BLTUL_I, INSN_MACRO, 0, I2|T3 }, -{"bltz", "s,p", 0x04000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, -{"bltzl", "s,p", 0x04020000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, -{"bltzal", "s,p", 0x04100000, 0xfc1f0000, CBD|RD_s|WR_31, 0, I1 }, -{"bltzall", "s,p", 0x04120000, 0xfc1f0000, CBL|RD_s|WR_31, 0, I2|T3 }, -{"bnez", "s,p", 0x14000000, 0xfc1f0000, CBD|RD_s, 0, I1 }, -{"bnezl", "s,p", 0x54000000, 0xfc1f0000, CBL|RD_s, 0, I2|T3 }, -{"bne", "s,t,p", 0x14000000, 0xfc000000, CBD|RD_s|RD_t, 0, I1 }, -{"bne", "s,I,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I1 }, -{"bnel", "s,t,p", 0x54000000, 0xfc000000, CBL|RD_s|RD_t, 0, I2|T3 }, -{"bnel", "s,I,p", 0, (int) M_BNEL_I, INSN_MACRO, 0, I2|T3 }, -{"break", "", 0x0000000d, 0xffffffff, TRAP, 0, I1 }, -{"break", "c", 0x0000000d, 0xfc00ffff, TRAP, 0, I1 }, -{"break", "c,q", 0x0000000d, 0xfc00003f, TRAP, 0, I1 }, -{"c.f.d", "S,T", 0x46200030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.f.d", "M,S,T", 0x46200030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.f.s", "S,T", 0x46000030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.f.s", "M,S,T", 0x46000030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.f.ps", "S,T", 0x46c00030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.f.ps", "S,T", 0x45600030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.f.ps", "M,S,T", 0x46c00030, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.un.d", "S,T", 0x46200031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.un.d", "M,S,T", 0x46200031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.un.s", "S,T", 0x46000031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.un.s", "M,S,T", 0x46000031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.un.ps", "S,T", 0x46c00031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.un.ps", "S,T", 0x45600031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.un.ps", "M,S,T", 0x46c00031, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.eq.d", "S,T", 0x46200032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.eq.d", "M,S,T", 0x46200032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.eq.s", "S,T", 0x46000032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.eq.s", "M,S,T", 0x46000032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.eq.ob", "Y,Q", 0x78000001, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"c.eq.ob", "S,T", 0x4ac00001, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.eq.ob", "S,T[e]", 0x48000001, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.eq.ob", "S,k", 0x4bc00001, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.eq.ps", "S,T", 0x46c00032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.eq.ps", "S,T", 0x45600032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.eq.ps", "M,S,T", 0x46c00032, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.eq.qh", "Y,Q", 0x78200001, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX }, -{"c.ueq.d", "S,T", 0x46200033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.ueq.d", "M,S,T", 0x46200033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.ueq.s", "S,T", 0x46000033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.ueq.s", "M,S,T", 0x46000033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.ueq.ps","S,T", 0x46c00033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.ueq.ps","S,T", 0x45600033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ueq.ps","M,S,T", 0x46c00033, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.olt.d", "S,T", 0x46200034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.olt.d", "M,S,T", 0x46200034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.olt.s", "S,T", 0x46000034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.olt.s", "M,S,T", 0x46000034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.olt.ps","S,T", 0x46c00034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.olt.ps","S,T", 0x45600034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.olt.ps","M,S,T", 0x46c00034, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.ult.d", "S,T", 0x46200035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.ult.d", "M,S,T", 0x46200035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.ult.s", "S,T", 0x46000035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.ult.s", "M,S,T", 0x46000035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.ult.ps","S,T", 0x46c00035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.ult.ps","S,T", 0x45600035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ult.ps","M,S,T", 0x46c00035, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.ole.d", "S,T", 0x46200036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.ole.d", "M,S,T", 0x46200036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.ole.s", "S,T", 0x46000036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.ole.s", "M,S,T", 0x46000036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.ole.ps","S,T", 0x46c00036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.ole.ps","S,T", 0x45600036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ole.ps","M,S,T", 0x46c00036, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.ule.d", "S,T", 0x46200037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.ule.d", "M,S,T", 0x46200037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.ule.s", "S,T", 0x46000037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.ule.s", "M,S,T", 0x46000037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.ule.ps","S,T", 0x46c00037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.ule.ps","S,T", 0x45600037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ule.ps","M,S,T", 0x46c00037, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.sf.d", "S,T", 0x46200038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.sf.d", "M,S,T", 0x46200038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.sf.s", "S,T", 0x46000038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.sf.s", "M,S,T", 0x46000038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.sf.ps", "S,T", 0x46c00038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.sf.ps", "S,T", 0x45600038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.sf.ps", "M,S,T", 0x46c00038, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.ngle.d","S,T", 0x46200039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.ngle.d","M,S,T", 0x46200039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.ngle.s","S,T", 0x46000039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.ngle.s","M,S,T", 0x46000039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.ngle.ps","S,T", 0x46c00039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.ngle.ps","S,T", 0x45600039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ngle.ps","M,S,T", 0x46c00039, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.seq.d", "S,T", 0x4620003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.seq.d", "M,S,T", 0x4620003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.seq.s", "S,T", 0x4600003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.seq.s", "M,S,T", 0x4600003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.seq.ps","S,T", 0x46c0003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.seq.ps","S,T", 0x4560003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.seq.ps","M,S,T", 0x46c0003a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.ngl.d", "S,T", 0x4620003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.ngl.d", "M,S,T", 0x4620003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.ngl.s", "S,T", 0x4600003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.ngl.s", "M,S,T", 0x4600003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.ngl.ps","S,T", 0x46c0003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.ngl.ps","S,T", 0x4560003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ngl.ps","M,S,T", 0x46c0003b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.lt.d", "S,T", 0x4620003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.lt.d", "M,S,T", 0x4620003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.lt.s", "S,T", 0x4600003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.lt.s", "M,S,T", 0x4600003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.lt.ob", "Y,Q", 0x78000004, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"c.lt.ob", "S,T", 0x4ac00004, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.lt.ob", "S,T[e]", 0x48000004, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.lt.ob", "S,k", 0x4bc00004, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.lt.ps", "S,T", 0x46c0003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.lt.ps", "S,T", 0x4560003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.lt.ps", "M,S,T", 0x46c0003c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.lt.qh", "Y,Q", 0x78200004, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX }, -{"c.nge.d", "S,T", 0x4620003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.nge.d", "M,S,T", 0x4620003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.nge.s", "S,T", 0x4600003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.nge.s", "M,S,T", 0x4600003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.nge.ps","S,T", 0x46c0003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.nge.ps","S,T", 0x4560003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.nge.ps","M,S,T", 0x46c0003d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.le.d", "S,T", 0x4620003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.le.d", "M,S,T", 0x4620003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.le.s", "S,T", 0x4600003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.le.s", "M,S,T", 0x4600003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.le.ob", "Y,Q", 0x78000005, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"c.le.ob", "S,T", 0x4ac00005, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.le.ob", "S,T[e]", 0x48000005, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.le.ob", "S,k", 0x4bc00005, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"c.le.ps", "S,T", 0x46c0003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.le.ps", "S,T", 0x4560003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.le.ps", "M,S,T", 0x46c0003e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"c.le.qh", "Y,Q", 0x78200005, 0xfc2007ff, WR_CC|RD_S|RD_T|FP_D, 0, MX }, -{"c.ngt.d", "S,T", 0x4620003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I1 }, -{"c.ngt.d", "M,S,T", 0x4620003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I4_32 }, -{"c.ngt.s", "S,T", 0x4600003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_S, 0, I1 }, -{"c.ngt.s", "M,S,T", 0x4600003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, I4_32 }, -{"c.ngt.ps","S,T", 0x46c0003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33|IL2F }, -{"c.ngt.ps","S,T", 0x4560003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ngt.ps","M,S,T", 0x46c0003f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, I5_33 }, -{"cabs.eq.d", "M,S,T", 0x46200072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.eq.ps", "M,S,T", 0x46c00072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.eq.s", "M,S,T", 0x46000072, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.f.d", "M,S,T", 0x46200070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.f.ps", "M,S,T", 0x46c00070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.f.s", "M,S,T", 0x46000070, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.le.d", "M,S,T", 0x4620007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.le.ps", "M,S,T", 0x46c0007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.le.s", "M,S,T", 0x4600007e, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.lt.d", "M,S,T", 0x4620007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.lt.ps", "M,S,T", 0x46c0007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.lt.s", "M,S,T", 0x4600007c, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.nge.d", "M,S,T", 0x4620007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.nge.ps","M,S,T", 0x46c0007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.nge.s", "M,S,T", 0x4600007d, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.ngl.d", "M,S,T", 0x4620007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ngl.ps","M,S,T", 0x46c0007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ngl.s", "M,S,T", 0x4600007b, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.ngle.d","M,S,T", 0x46200079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ngle.ps","M,S,T",0x46c00079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ngle.s","M,S,T", 0x46000079, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.ngt.d", "M,S,T", 0x4620007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ngt.ps","M,S,T", 0x46c0007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ngt.s", "M,S,T", 0x4600007f, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.ole.d", "M,S,T", 0x46200076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ole.ps","M,S,T", 0x46c00076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ole.s", "M,S,T", 0x46000076, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.olt.d", "M,S,T", 0x46200074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.olt.ps","M,S,T", 0x46c00074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.olt.s", "M,S,T", 0x46000074, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.seq.d", "M,S,T", 0x4620007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.seq.ps","M,S,T", 0x46c0007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.seq.s", "M,S,T", 0x4600007a, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.sf.d", "M,S,T", 0x46200078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.sf.ps", "M,S,T", 0x46c00078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.sf.s", "M,S,T", 0x46000078, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.ueq.d", "M,S,T", 0x46200073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ueq.ps","M,S,T", 0x46c00073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ueq.s", "M,S,T", 0x46000073, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.ule.d", "M,S,T", 0x46200077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ule.ps","M,S,T", 0x46c00077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ule.s", "M,S,T", 0x46000077, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.ult.d", "M,S,T", 0x46200075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ult.ps","M,S,T", 0x46c00075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.ult.s", "M,S,T", 0x46000075, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -{"cabs.un.d", "M,S,T", 0x46200071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.un.ps", "M,S,T", 0x46c00071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_D, 0, M3D }, -{"cabs.un.s", "M,S,T", 0x46000071, 0xffe000ff, RD_S|RD_T|WR_CC|FP_S, 0, M3D }, -/* CW4010 instructions which are aliases for the cache instruction. */ -{"flushi", "", 0xbc010000, 0xffffffff, 0, 0, L1 }, -{"flushd", "", 0xbc020000, 0xffffffff, 0, 0, L1 }, -{"flushid", "", 0xbc030000, 0xffffffff, 0, 0, L1 }, -{"wb", "o(b)", 0xbc040000, 0xfc1f0000, SM|RD_b, 0, L1 }, -{"cache", "k,o(b)", 0xbc000000, 0xfc000000, RD_b, 0, I3_32|T3}, -{"cache", "k,A(b)", 0, (int) M_CACHE_AB, INSN_MACRO, 0, I3_32|T3}, -{"ceil.l.d", "D,S", 0x4620000a, 0xffff003f, WR_D|RD_S|FP_D, 0, I3_33 }, -{"ceil.l.s", "D,S", 0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3_33 }, -{"ceil.w.d", "D,S", 0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, -{"ceil.w.s", "D,S", 0x4600000e, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, -{"cfc0", "t,G", 0x40400000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I1 }, -{"cfc1", "t,G", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 }, -{"cfc1", "t,S", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 }, -/* cfc2 is at the bottom of the table. */ -/* cfc3 is at the bottom of the table. */ -{"cftc1", "d,E", 0x41000023, 0xffe007ff, TRAP|LCD|WR_d|RD_C1|FP_S, 0, MT32 }, -{"cftc1", "d,T", 0x41000023, 0xffe007ff, TRAP|LCD|WR_d|RD_C1|FP_S, 0, MT32 }, -{"cftc2", "d,E", 0x41000025, 0xffe007ff, TRAP|LCD|WR_d|RD_C2, 0, MT32 }, -{"clo", "U,s", 0x70000021, 0xfc0007ff, WR_d|WR_t|RD_s, 0, I32|N55 }, -{"clz", "U,s", 0x70000020, 0xfc0007ff, WR_d|WR_t|RD_s, 0, I32|N55 }, -{"ctc0", "t,G", 0x40c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, -{"ctc1", "t,G", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, 0, I1 }, -{"ctc1", "t,S", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, 0, I1 }, -/* ctc2 is at the bottom of the table. */ -/* ctc3 is at the bottom of the table. */ -{"cttc1", "t,g", 0x41800023, 0xffe007ff, TRAP|COD|RD_t|WR_CC|FP_S, 0, MT32 }, -{"cttc1", "t,S", 0x41800023, 0xffe007ff, TRAP|COD|RD_t|WR_CC|FP_S, 0, MT32 }, -{"cttc2", "t,g", 0x41800025, 0xffe007ff, TRAP|COD|RD_t|WR_CC, 0, MT32 }, -{"cvt.d.l", "D,S", 0x46a00021, 0xffff003f, WR_D|RD_S|FP_D, 0, I3_33 }, -{"cvt.d.s", "D,S", 0x46000021, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, -{"cvt.d.w", "D,S", 0x46800021, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, -{"cvt.l.d", "D,S", 0x46200025, 0xffff003f, WR_D|RD_S|FP_D, 0, I3_33 }, -{"cvt.l.s", "D,S", 0x46000025, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3_33 }, -{"cvt.s.l", "D,S", 0x46a00020, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3_33 }, -{"cvt.s.d", "D,S", 0x46200020, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, -{"cvt.s.w", "D,S", 0x46800020, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, -{"cvt.s.pl","D,S", 0x46c00028, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I5_33 }, -{"cvt.s.pu","D,S", 0x46c00020, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I5_33 }, -{"cvt.w.d", "D,S", 0x46200024, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I1 }, -{"cvt.w.s", "D,S", 0x46000024, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, -{"cvt.ps.pw", "D,S", 0x46800026, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, M3D }, -{"cvt.ps.s","D,V,T", 0x46000026, 0xffe0003f, WR_D|RD_S|RD_T|FP_S|FP_D, 0, I5_33 }, -{"cvt.pw.ps", "D,S", 0x46c00024, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, M3D }, -{"dabs", "d,v", 0, (int) M_DABS, INSN_MACRO, 0, I3 }, -{"dadd", "d,v,t", 0x0000002c, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, -{"dadd", "t,r,I", 0, (int) M_DADD_I, INSN_MACRO, 0, I3 }, -{"dadd", "D,S,T", 0x45e00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"dadd", "D,S,T", 0x4b60000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"daddi", "t,r,j", 0x60000000, 0xfc000000, WR_t|RD_s, 0, I3 }, -{"daddiu", "t,r,j", 0x64000000, 0xfc000000, WR_t|RD_s, 0, I3 }, -{"daddu", "d,v,t", 0x0000002d, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, -{"daddu", "t,r,I", 0, (int) M_DADDU_I, INSN_MACRO, 0, I3 }, -{"dbreak", "", 0x7000003f, 0xffffffff, 0, 0, N5 }, -{"dclo", "U,s", 0x70000025, 0xfc0007ff, RD_s|WR_d|WR_t, 0, I64|N55 }, -{"dclz", "U,s", 0x70000024, 0xfc0007ff, RD_s|WR_d|WR_t, 0, I64|N55 }, -/* dctr and dctw are used on the r5000. */ -{"dctr", "o(b)", 0xbc050000, 0xfc1f0000, RD_b, 0, I3 }, -{"dctw", "o(b)", 0xbc090000, 0xfc1f0000, RD_b, 0, I3 }, -{"deret", "", 0x4200001f, 0xffffffff, 0, 0, I32|G2 }, -{"dext", "t,r,I,+I", 0, (int) M_DEXT, INSN_MACRO, 0, I65 }, -{"dext", "t,r,+A,+C", 0x7c000003, 0xfc00003f, WR_t|RD_s, 0, I65 }, -{"dextm", "t,r,+A,+G", 0x7c000001, 0xfc00003f, WR_t|RD_s, 0, I65 }, -{"dextu", "t,r,+E,+H", 0x7c000002, 0xfc00003f, WR_t|RD_s, 0, I65 }, -/* For ddiv, see the comments about div. */ -{"ddiv", "z,s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, -{"ddiv", "d,v,t", 0, (int) M_DDIV_3, INSN_MACRO, 0, I3 }, -{"ddiv", "d,v,I", 0, (int) M_DDIV_3I, INSN_MACRO, 0, I3 }, -/* For ddivu, see the comments about div. */ -{"ddivu", "z,s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, -{"ddivu", "d,v,t", 0, (int) M_DDIVU_3, INSN_MACRO, 0, I3 }, -{"ddivu", "d,v,I", 0, (int) M_DDIVU_3I, INSN_MACRO, 0, I3 }, -{"di", "", 0x41606000, 0xffffffff, WR_t|WR_C0, 0, I33 }, -{"di", "t", 0x41606000, 0xffe0ffff, WR_t|WR_C0, 0, I33 }, -{"dins", "t,r,I,+I", 0, (int) M_DINS, INSN_MACRO, 0, I65 }, -{"dins", "t,r,+A,+B", 0x7c000007, 0xfc00003f, WR_t|RD_s, 0, I65 }, -{"dinsm", "t,r,+A,+F", 0x7c000005, 0xfc00003f, WR_t|RD_s, 0, I65 }, -{"dinsu", "t,r,+E,+F", 0x7c000006, 0xfc00003f, WR_t|RD_s, 0, I65 }, -/* The MIPS assembler treats the div opcode with two operands as - though the first operand appeared twice (the first operand is both - a source and a destination). To get the div machine instruction, - you must use an explicit destination of $0. */ -{"div", "z,s,t", 0x0000001a, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, -{"div", "z,t", 0x0000001a, 0xffe0ffff, RD_s|RD_t|WR_HILO, 0, I1 }, -{"div", "d,v,t", 0, (int) M_DIV_3, INSN_MACRO, 0, I1 }, -{"div", "d,v,I", 0, (int) M_DIV_3I, INSN_MACRO, 0, I1 }, -{"div.d", "D,V,T", 0x46200003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, -{"div.s", "D,V,T", 0x46000003, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, -{"div.ps", "D,V,T", 0x46c00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, SB1 }, -/* For divu, see the comments about div. */ -{"divu", "z,s,t", 0x0000001b, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, -{"divu", "z,t", 0x0000001b, 0xffe0ffff, RD_s|RD_t|WR_HILO, 0, I1 }, -{"divu", "d,v,t", 0, (int) M_DIVU_3, INSN_MACRO, 0, I1 }, -{"divu", "d,v,I", 0, (int) M_DIVU_3I, INSN_MACRO, 0, I1 }, -{"dla", "t,A(b)", 0, (int) M_DLA_AB, INSN_MACRO, 0, I3 }, -{"dlca", "t,A(b)", 0, (int) M_DLCA_AB, INSN_MACRO, 0, I3 }, -{"dli", "t,j", 0x24000000, 0xffe00000, WR_t, 0, I3 }, /* addiu */ -{"dli", "t,i", 0x34000000, 0xffe00000, WR_t, 0, I3 }, /* ori */ -{"dli", "t,I", 0, (int) M_DLI, INSN_MACRO, 0, I3 }, -{"dmacc", "d,s,t", 0x00000029, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmacchi", "d,s,t", 0x00000229, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmacchis", "d,s,t", 0x00000629, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmacchiu", "d,s,t", 0x00000269, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmacchius", "d,s,t", 0x00000669, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmaccs", "d,s,t", 0x00000429, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmaccu", "d,s,t", 0x00000069, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmaccus", "d,s,t", 0x00000469, 0xfc0007ff, RD_s|RD_t|WR_LO|WR_d, 0, N412 }, -{"dmadd16", "s,t", 0x00000029, 0xfc00ffff, RD_s|RD_t|MOD_LO, 0, N411 }, -{"dmfc0", "t,G", 0x40200000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I3 }, -{"dmfc0", "t,+D", 0x40200000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I64 }, -{"dmfc0", "t,G,H", 0x40200000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I64 }, -{"dmt", "", 0x41600bc1, 0xffffffff, TRAP, 0, MT32 }, -{"dmt", "t", 0x41600bc1, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, -{"dmtc0", "t,G", 0x40a00000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC, 0, I3 }, -{"dmtc0", "t,+D", 0x40a00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I64 }, -{"dmtc0", "t,G,H", 0x40a00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I64 }, -{"dmfc1", "t,S", 0x44200000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I3 }, -{"dmfc1", "t,G", 0x44200000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I3 }, -{"dmtc1", "t,S", 0x44a00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I3 }, -{"dmtc1", "t,G", 0x44a00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I3 }, -/* dmfc2 is at the bottom of the table. */ -/* dmtc2 is at the bottom of the table. */ -/* dmfc3 is at the bottom of the table. */ -/* dmtc3 is at the bottom of the table. */ -{"dmul", "d,v,t", 0, (int) M_DMUL, INSN_MACRO, 0, I3 }, -{"dmul", "d,v,I", 0, (int) M_DMUL_I, INSN_MACRO, 0, I3 }, -{"dmulo", "d,v,t", 0, (int) M_DMULO, INSN_MACRO, 0, I3 }, -{"dmulo", "d,v,I", 0, (int) M_DMULO_I, INSN_MACRO, 0, I3 }, -{"dmulou", "d,v,t", 0, (int) M_DMULOU, INSN_MACRO, 0, I3 }, -{"dmulou", "d,v,I", 0, (int) M_DMULOU_I, INSN_MACRO, 0, I3 }, -{"dmult", "s,t", 0x0000001c, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, -{"dmultu", "s,t", 0x0000001d, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, -{"dneg", "d,w", 0x0000002e, 0xffe007ff, WR_d|RD_t, 0, I3 }, /* dsub 0 */ -{"dnegu", "d,w", 0x0000002f, 0xffe007ff, WR_d|RD_t, 0, I3 }, /* dsubu 0*/ -{"drem", "z,s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, -{"drem", "d,v,t", 3, (int) M_DREM_3, INSN_MACRO, 0, I3 }, -{"drem", "d,v,I", 3, (int) M_DREM_3I, INSN_MACRO, 0, I3 }, -{"dremu", "z,s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I3 }, -{"dremu", "d,v,t", 3, (int) M_DREMU_3, INSN_MACRO, 0, I3 }, -{"dremu", "d,v,I", 3, (int) M_DREMU_3I, INSN_MACRO, 0, I3 }, -{"dret", "", 0x7000003e, 0xffffffff, 0, 0, N5 }, -{"drol", "d,v,t", 0, (int) M_DROL, INSN_MACRO, 0, I3 }, -{"drol", "d,v,I", 0, (int) M_DROL_I, INSN_MACRO, 0, I3 }, -{"dror", "d,v,t", 0, (int) M_DROR, INSN_MACRO, 0, I3 }, -{"dror", "d,v,I", 0, (int) M_DROR_I, INSN_MACRO, 0, I3 }, -{"dror", "d,w,<", 0x0020003a, 0xffe0003f, WR_d|RD_t, 0, N5|I65 }, -{"drorv", "d,t,s", 0x00000056, 0xfc0007ff, RD_t|RD_s|WR_d, 0, N5|I65 }, -{"dror32", "d,w,<", 0x0020003e, 0xffe0003f, WR_d|RD_t, 0, N5|I65 }, -{"drotl", "d,v,t", 0, (int) M_DROL, INSN_MACRO, 0, I65 }, -{"drotl", "d,v,I", 0, (int) M_DROL_I, INSN_MACRO, 0, I65 }, -{"drotr", "d,v,t", 0, (int) M_DROR, INSN_MACRO, 0, I65 }, -{"drotr", "d,v,I", 0, (int) M_DROR_I, INSN_MACRO, 0, I65 }, -{"drotrv", "d,t,s", 0x00000056, 0xfc0007ff, RD_t|RD_s|WR_d, 0, I65 }, -{"drotr32", "d,w,<", 0x0020003e, 0xffe0003f, WR_d|RD_t, 0, I65 }, -{"dsbh", "d,w", 0x7c0000a4, 0xffe007ff, WR_d|RD_t, 0, I65 }, -{"dshd", "d,w", 0x7c000164, 0xffe007ff, WR_d|RD_t, 0, I65 }, -{"dsllv", "d,t,s", 0x00000014, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, -{"dsll32", "d,w,<", 0x0000003c, 0xffe0003f, WR_d|RD_t, 0, I3 }, -{"dsll", "d,w,s", 0x00000014, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, /* dsllv */ -{"dsll", "d,w,>", 0x0000003c, 0xffe0003f, WR_d|RD_t, 0, I3 }, /* dsll32 */ -{"dsll", "d,w,<", 0x00000038, 0xffe0003f, WR_d|RD_t, 0, I3 }, -{"dsll", "D,S,T", 0x45a00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"dsll", "D,S,T", 0x4b20000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"dsrav", "d,t,s", 0x00000017, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, -{"dsra32", "d,w,<", 0x0000003f, 0xffe0003f, WR_d|RD_t, 0, I3 }, -{"dsra", "d,w,s", 0x00000017, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, /* dsrav */ -{"dsra", "d,w,>", 0x0000003f, 0xffe0003f, WR_d|RD_t, 0, I3 }, /* dsra32 */ -{"dsra", "d,w,<", 0x0000003b, 0xffe0003f, WR_d|RD_t, 0, I3 }, -{"dsra", "D,S,T", 0x45e00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"dsra", "D,S,T", 0x4b60000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"dsrlv", "d,t,s", 0x00000016, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, -{"dsrl32", "d,w,<", 0x0000003e, 0xffe0003f, WR_d|RD_t, 0, I3 }, -{"dsrl", "d,w,s", 0x00000016, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I3 }, /* dsrlv */ -{"dsrl", "d,w,>", 0x0000003e, 0xffe0003f, WR_d|RD_t, 0, I3 }, /* dsrl32 */ -{"dsrl", "d,w,<", 0x0000003a, 0xffe0003f, WR_d|RD_t, 0, I3 }, -{"dsrl", "D,S,T", 0x45a00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"dsrl", "D,S,T", 0x4b20000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"dsub", "d,v,t", 0x0000002e, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, -{"dsub", "d,v,I", 0, (int) M_DSUB_I, INSN_MACRO, 0, I3 }, -{"dsub", "D,S,T", 0x45e00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"dsub", "D,S,T", 0x4b60000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"dsubu", "d,v,t", 0x0000002f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I3 }, -{"dsubu", "d,v,I", 0, (int) M_DSUBU_I, INSN_MACRO, 0, I3 }, -{"dvpe", "", 0x41600001, 0xffffffff, TRAP, 0, MT32 }, -{"dvpe", "t", 0x41600001, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, -{"ei", "", 0x41606020, 0xffffffff, WR_t|WR_C0, 0, I33 }, -{"ei", "t", 0x41606020, 0xffe0ffff, WR_t|WR_C0, 0, I33 }, -{"emt", "", 0x41600be1, 0xffffffff, TRAP, 0, MT32 }, -{"emt", "t", 0x41600be1, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, -{"eret", "", 0x42000018, 0xffffffff, 0, 0, I3_32 }, -{"evpe", "", 0x41600021, 0xffffffff, TRAP, 0, MT32 }, -{"evpe", "t", 0x41600021, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, -{"ext", "t,r,+A,+C", 0x7c000000, 0xfc00003f, WR_t|RD_s, 0, I33 }, -{"floor.l.d", "D,S", 0x4620000b, 0xffff003f, WR_D|RD_S|FP_D, 0, I3_33 }, -{"floor.l.s", "D,S", 0x4600000b, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3_33 }, -{"floor.w.d", "D,S", 0x4620000f, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, -{"floor.w.s", "D,S", 0x4600000f, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, -{"hibernate","", 0x42000023, 0xffffffff, 0, 0, V1 }, -{"ins", "t,r,+A,+B", 0x7c000004, 0xfc00003f, WR_t|RD_s, 0, I33 }, -{"jr", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, 0, I1 }, -/* jr.hb is officially MIPS{32,64}R2, but it works on R1 as jr with - the same hazard barrier effect. */ -{"jr.hb", "s", 0x00000408, 0xfc1fffff, UBD|RD_s, 0, I32 }, -{"j", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, 0, I1 }, /* jr */ -/* SVR4 PIC code requires special handling for j, so it must be a - macro. */ -{"j", "a", 0, (int) M_J_A, INSN_MACRO, 0, I1 }, -/* This form of j is used by the disassembler and internally by the - assembler, but will never match user input (because the line above - will match first). */ -{"j", "a", 0x08000000, 0xfc000000, UBD, 0, I1 }, -{"jalr", "s", 0x0000f809, 0xfc1fffff, UBD|RD_s|WR_d, 0, I1 }, -{"jalr", "d,s", 0x00000009, 0xfc1f07ff, UBD|RD_s|WR_d, 0, I1 }, -/* jalr.hb is officially MIPS{32,64}R2, but it works on R1 as jalr - with the same hazard barrier effect. */ -{"jalr.hb", "s", 0x0000fc09, 0xfc1fffff, UBD|RD_s|WR_d, 0, I32 }, -{"jalr.hb", "d,s", 0x00000409, 0xfc1f07ff, UBD|RD_s|WR_d, 0, I32 }, -/* SVR4 PIC code requires special handling for jal, so it must be a - macro. */ -{"jal", "d,s", 0, (int) M_JAL_2, INSN_MACRO, 0, I1 }, -{"jal", "s", 0, (int) M_JAL_1, INSN_MACRO, 0, I1 }, -{"jal", "a", 0, (int) M_JAL_A, INSN_MACRO, 0, I1 }, -/* This form of jal is used by the disassembler and internally by the - assembler, but will never match user input (because the line above - will match first). */ -{"jal", "a", 0x0c000000, 0xfc000000, UBD|WR_31, 0, I1 }, -{"jalx", "a", 0x74000000, 0xfc000000, UBD|WR_31, 0, I16 }, -{"la", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, 0, I1 }, -{"lb", "t,o(b)", 0x80000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, -{"lb", "t,A(b)", 0, (int) M_LB_AB, INSN_MACRO, 0, I1 }, -{"lbu", "t,o(b)", 0x90000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, -{"lbu", "t,A(b)", 0, (int) M_LBU_AB, INSN_MACRO, 0, I1 }, -{"lca", "t,A(b)", 0, (int) M_LCA_AB, INSN_MACRO, 0, I1 }, -{"ld", "t,o(b)", 0xdc000000, 0xfc000000, WR_t|RD_b, 0, I3 }, -{"ld", "t,o(b)", 0, (int) M_LD_OB, INSN_MACRO, 0, I1 }, -{"ld", "t,A(b)", 0, (int) M_LD_AB, INSN_MACRO, 0, I1 }, -{"ldc1", "T,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, 0, I2 }, -{"ldc1", "E,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, 0, I2 }, -{"ldc1", "T,A(b)", 0, (int) M_LDC1_AB, INSN_MACRO, 0, I2 }, -{"ldc1", "E,A(b)", 0, (int) M_LDC1_AB, INSN_MACRO, 0, I2 }, -{"l.d", "T,o(b)", 0xd4000000, 0xfc000000, CLD|RD_b|WR_T|FP_D, 0, I2 }, /* ldc1 */ -{"l.d", "T,o(b)", 0, (int) M_L_DOB, INSN_MACRO, 0, I1 }, -{"l.d", "T,A(b)", 0, (int) M_L_DAB, INSN_MACRO, 0, I1 }, -{"ldc2", "E,o(b)", 0xd8000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I2 }, -{"ldc2", "E,A(b)", 0, (int) M_LDC2_AB, INSN_MACRO, 0, I2 }, -{"ldc3", "E,o(b)", 0xdc000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I2 }, -{"ldc3", "E,A(b)", 0, (int) M_LDC3_AB, INSN_MACRO, 0, I2 }, -{"ldl", "t,o(b)", 0x68000000, 0xfc000000, LDD|WR_t|RD_b, 0, I3 }, -{"ldl", "t,A(b)", 0, (int) M_LDL_AB, INSN_MACRO, 0, I3 }, -{"ldr", "t,o(b)", 0x6c000000, 0xfc000000, LDD|WR_t|RD_b, 0, I3 }, -{"ldr", "t,A(b)", 0, (int) M_LDR_AB, INSN_MACRO, 0, I3 }, -{"ldxc1", "D,t(b)", 0x4c000001, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I4_33 }, -{"lh", "t,o(b)", 0x84000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, -{"lh", "t,A(b)", 0, (int) M_LH_AB, INSN_MACRO, 0, I1 }, -{"lhu", "t,o(b)", 0x94000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, -{"lhu", "t,A(b)", 0, (int) M_LHU_AB, INSN_MACRO, 0, I1 }, -/* li is at the start of the table. */ -{"li.d", "t,F", 0, (int) M_LI_D, INSN_MACRO, 0, I1 }, -{"li.d", "T,L", 0, (int) M_LI_DD, INSN_MACRO, 0, I1 }, -{"li.s", "t,f", 0, (int) M_LI_S, INSN_MACRO, 0, I1 }, -{"li.s", "T,l", 0, (int) M_LI_SS, INSN_MACRO, 0, I1 }, -{"ll", "t,o(b)", 0xc0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2 }, -{"ll", "t,A(b)", 0, (int) M_LL_AB, INSN_MACRO, 0, I2 }, -{"lld", "t,o(b)", 0xd0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I3 }, -{"lld", "t,A(b)", 0, (int) M_LLD_AB, INSN_MACRO, 0, I3 }, -{"lui", "t,u", 0x3c000000, 0xffe00000, WR_t, 0, I1 }, -{"luxc1", "D,t(b)", 0x4c000005, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I5_33|N55}, -{"lw", "t,o(b)", 0x8c000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, -{"lw", "t,A(b)", 0, (int) M_LW_AB, INSN_MACRO, 0, I1 }, -{"lwc0", "E,o(b)", 0xc0000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I1 }, -{"lwc0", "E,A(b)", 0, (int) M_LWC0_AB, INSN_MACRO, 0, I1 }, -{"lwc1", "T,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, 0, I1 }, -{"lwc1", "E,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, 0, I1 }, -{"lwc1", "T,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, 0, I1 }, -{"lwc1", "E,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, 0, I1 }, -{"l.s", "T,o(b)", 0xc4000000, 0xfc000000, CLD|RD_b|WR_T|FP_S, 0, I1 }, /* lwc1 */ -{"l.s", "T,A(b)", 0, (int) M_LWC1_AB, INSN_MACRO, 0, I1 }, -{"lwc2", "E,o(b)", 0xc8000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I1 }, -{"lwc2", "E,A(b)", 0, (int) M_LWC2_AB, INSN_MACRO, 0, I1 }, -{"lwc3", "E,o(b)", 0xcc000000, 0xfc000000, CLD|RD_b|WR_CC, 0, I1 }, -{"lwc3", "E,A(b)", 0, (int) M_LWC3_AB, INSN_MACRO, 0, I1 }, -{"lwl", "t,o(b)", 0x88000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, -{"lwl", "t,A(b)", 0, (int) M_LWL_AB, INSN_MACRO, 0, I1 }, -{"lcache", "t,o(b)", 0x88000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2 }, /* same */ -{"lcache", "t,A(b)", 0, (int) M_LWL_AB, INSN_MACRO, 0, I2 }, /* as lwl */ -{"lwr", "t,o(b)", 0x98000000, 0xfc000000, LDD|RD_b|WR_t, 0, I1 }, -{"lwr", "t,A(b)", 0, (int) M_LWR_AB, INSN_MACRO, 0, I1 }, -{"flush", "t,o(b)", 0x98000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2 }, /* same */ -{"flush", "t,A(b)", 0, (int) M_LWR_AB, INSN_MACRO, 0, I2 }, /* as lwr */ -{"fork", "d,s,t", 0x7c000008, 0xfc0007ff, TRAP|WR_d|RD_s|RD_t, 0, MT32 }, -{"lwu", "t,o(b)", 0x9c000000, 0xfc000000, LDD|RD_b|WR_t, 0, I3 }, -{"lwu", "t,A(b)", 0, (int) M_LWU_AB, INSN_MACRO, 0, I3 }, -{"lwxc1", "D,t(b)", 0x4c000000, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_S, 0, I4_33 }, -{"lwxs", "d,t(b)", 0x70000088, 0xfc0007ff, LDD|RD_b|RD_t|WR_d, 0, SMT }, -{"macc", "d,s,t", 0x00000028, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"macc", "d,s,t", 0x00000158, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"maccs", "d,s,t", 0x00000428, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"macchi", "d,s,t", 0x00000228, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"macchi", "d,s,t", 0x00000358, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"macchis", "d,s,t", 0x00000628, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"macchiu", "d,s,t", 0x00000268, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"macchiu", "d,s,t", 0x00000359, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"macchius","d,s,t", 0x00000668, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"maccu", "d,s,t", 0x00000068, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"maccu", "d,s,t", 0x00000159, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"maccus", "d,s,t", 0x00000468, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, -{"mad", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3 }, -{"madu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3 }, -{"madd.d", "D,R,S,T", 0x4c000021, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4_33 }, -{"madd.d", "D,S,T", 0x46200018, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"madd.d", "D,S,T", 0x72200018, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"madd.s", "D,R,S,T", 0x4c000020, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4_33 }, -{"madd.s", "D,S,T", 0x46000018, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"madd.s", "D,S,T", 0x72000018, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"madd.ps", "D,R,S,T", 0x4c000026, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5_33 }, -{"madd.ps", "D,S,T", 0x45600018, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"madd.ps", "D,S,T", 0x71600018, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"madd", "s,t", 0x0000001c, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, -{"madd", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, -{"madd", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, G1 }, -{"madd", "7,s,t", 0x70000000, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"madd", "d,s,t", 0x70000000, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, -{"maddp", "s,t", 0x70000441, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, SMT }, -{"maddu", "s,t", 0x0000001d, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, -{"maddu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, -{"maddu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, G1 }, -{"maddu", "7,s,t", 0x70000001, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"maddu", "d,s,t", 0x70000001, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, -{"madd16", "s,t", 0x00000028, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, N411 }, -{"max.ob", "X,Y,Q", 0x78000007, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"max.ob", "D,S,T", 0x4ac00007, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"max.ob", "D,S,T[e]", 0x48000007, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"max.ob", "D,S,k", 0x4bc00007, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"max.qh", "X,Y,Q", 0x78200007, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"mfpc", "t,P", 0x4000c801, 0xffe0ffc1, LCD|WR_t|RD_C0, 0, M1|N5 }, -{"mfps", "t,P", 0x4000c800, 0xffe0ffc1, LCD|WR_t|RD_C0, 0, M1|N5 }, -{"mftacx", "d", 0x41020021, 0xffff07ff, TRAP|WR_d|RD_a, 0, MT32 }, -{"mftacx", "d,*", 0x41020021, 0xfff307ff, TRAP|WR_d|RD_a, 0, MT32 }, -{"mftc0", "d,+t", 0x41000000, 0xffe007ff, TRAP|LCD|WR_d|RD_C0, 0, MT32 }, -{"mftc0", "d,+T", 0x41000000, 0xffe007f8, TRAP|LCD|WR_d|RD_C0, 0, MT32 }, -{"mftc0", "d,E,H", 0x41000000, 0xffe007f8, TRAP|LCD|WR_d|RD_C0, 0, MT32 }, -{"mftc1", "d,T", 0x41000022, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_S, 0, MT32 }, -{"mftc1", "d,E", 0x41000022, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_S, 0, MT32 }, -{"mftc2", "d,E", 0x41000024, 0xffe007ff, TRAP|LCD|WR_d|RD_C2, 0, MT32 }, -{"mftdsp", "d", 0x41100021, 0xffff07ff, TRAP|WR_d, 0, MT32 }, -{"mftgpr", "d,t", 0x41000020, 0xffe007ff, TRAP|WR_d|RD_t, 0, MT32 }, -{"mfthc1", "d,T", 0x41000032, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_D, 0, MT32 }, -{"mfthc1", "d,E", 0x41000032, 0xffe007ff, TRAP|LCD|WR_d|RD_T|FP_D, 0, MT32 }, -{"mfthc2", "d,E", 0x41000034, 0xffe007ff, TRAP|LCD|WR_d|RD_C2, 0, MT32 }, -{"mfthi", "d", 0x41010021, 0xffff07ff, TRAP|WR_d|RD_a, 0, MT32 }, -{"mfthi", "d,*", 0x41010021, 0xfff307ff, TRAP|WR_d|RD_a, 0, MT32 }, -{"mftlo", "d", 0x41000021, 0xffff07ff, TRAP|WR_d|RD_a, 0, MT32 }, -{"mftlo", "d,*", 0x41000021, 0xfff307ff, TRAP|WR_d|RD_a, 0, MT32 }, -{"mftr", "d,t,!,H,$", 0x41000000, 0xffe007c8, TRAP|WR_d, 0, MT32 }, -{"mfc0", "t,G", 0x40000000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I1 }, -{"mfc0", "t,+D", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I32 }, -{"mfc0", "t,G,H", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I32 }, -{"mfc1", "t,S", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, 0, I1 }, -{"mfc1", "t,G", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, 0, I1 }, -{"mfhc1", "t,S", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I33 }, -{"mfhc1", "t,G", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I33 }, -/* mfc2 is at the bottom of the table. */ -/* mfhc2 is at the bottom of the table. */ -/* mfc3 is at the bottom of the table. */ -{"mfdr", "t,G", 0x7000003d, 0xffe007ff, LCD|WR_t|RD_C0, 0, N5 }, -{"mfhi", "d", 0x00000010, 0xffff07ff, WR_d|RD_HI, 0, I1 }, -{"mfhi", "d,9", 0x00000010, 0xff9f07ff, WR_d|RD_HI, 0, D32 }, -{"mflo", "d", 0x00000012, 0xffff07ff, WR_d|RD_LO, 0, I1 }, -{"mflo", "d,9", 0x00000012, 0xff9f07ff, WR_d|RD_LO, 0, D32 }, -{"mflhxu", "d", 0x00000052, 0xffff07ff, WR_d|MOD_HILO, 0, SMT }, -{"min.ob", "X,Y,Q", 0x78000006, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"min.ob", "D,S,T", 0x4ac00006, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"min.ob", "D,S,T[e]", 0x48000006, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"min.ob", "D,S,k", 0x4bc00006, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"min.qh", "X,Y,Q", 0x78200006, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"mov.d", "D,S", 0x46200006, 0xffff003f, WR_D|RD_S|FP_D, 0, I1 }, -{"mov.s", "D,S", 0x46000006, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, -{"mov.ps", "D,S", 0x46c00006, 0xffff003f, WR_D|RD_S|FP_D, 0, I5_33|IL2F }, -{"mov.ps", "D,S", 0x45600006, 0xffff003f, WR_D|RD_S|FP_D, 0, IL2E }, -{"movf", "d,s,N", 0x00000001, 0xfc0307ff, WR_d|RD_s|RD_CC|FP_S|FP_D, 0, I4_32 }, -{"movf.d", "D,S,N", 0x46200011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I4_32 }, -{"movf.l", "D,S,N", 0x46a00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, -{"movf.l", "X,Y,N", 0x46a00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, -{"movf.s", "D,S,N", 0x46000011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, 0, I4_32 }, -{"movf.ps", "D,S,N", 0x46c00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I5_33 }, -{"movn", "d,v,t", 0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4_32|IL2E|IL2F }, -{"movnz", "d,v,t", 0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL2E|IL2F }, -{"ffc", "d,v", 0x0000000b, 0xfc1f07ff, WR_d|RD_s, 0, L1 }, -{"movn.d", "D,S,t", 0x46200013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I4_32 }, -{"movn.l", "D,S,t", 0x46a00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, -{"movn.l", "X,Y,t", 0x46a00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, -{"movn.s", "D,S,t", 0x46000013, 0xffe0003f, WR_D|RD_S|RD_t|FP_S, 0, I4_32 }, -{"movn.ps", "D,S,t", 0x46c00013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I5_33 }, -{"movt", "d,s,N", 0x00010001, 0xfc0307ff, WR_d|RD_s|RD_CC|FP_S|FP_D, 0, I4_32 }, -{"movt.d", "D,S,N", 0x46210011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I4_32 }, -{"movt.l", "D,S,N", 0x46a10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, -{"movt.l", "X,Y,N", 0x46a10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, -{"movt.s", "D,S,N", 0x46010011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, 0, I4_32 }, -{"movt.ps", "D,S,N", 0x46c10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I5_33 }, -{"movz", "d,v,t", 0x0000000a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4_32|IL2E|IL2F }, -{"ffs", "d,v", 0x0000000a, 0xfc1f07ff, WR_d|RD_s, 0, L1 }, -{"movz.d", "D,S,t", 0x46200012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I4_32 }, -{"movz.l", "D,S,t", 0x46a00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, -{"movz.l", "X,Y,t", 0x46a00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, -{"movz.s", "D,S,t", 0x46000012, 0xffe0003f, WR_D|RD_S|RD_t|FP_S, 0, I4_32 }, -{"movz.ps", "D,S,t", 0x46c00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I5_33 }, -{"msac", "d,s,t", 0x000001d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"msacu", "d,s,t", 0x000001d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"msachi", "d,s,t", 0x000003d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"msachiu", "d,s,t", 0x000003d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -/* move is at the top of the table. */ -{"msgn.qh", "X,Y,Q", 0x78200000, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"msub.d", "D,R,S,T", 0x4c000029, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4_33 }, -{"msub.d", "D,S,T", 0x46200019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"msub.d", "D,S,T", 0x72200019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"msub.s", "D,R,S,T", 0x4c000028, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4_33 }, -{"msub.s", "D,S,T", 0x46000019, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"msub.s", "D,S,T", 0x72000019, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"msub.ps", "D,R,S,T", 0x4c00002e, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5_33 }, -{"msub.ps", "D,S,T", 0x45600019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"msub.ps", "D,S,T", 0x71600019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"msub", "s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, -{"msub", "s,t", 0x70000004, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, -{"msub", "7,s,t", 0x70000004, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"msubu", "s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, -{"msubu", "s,t", 0x70000005, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, -{"msubu", "7,s,t", 0x70000005, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"mtpc", "t,P", 0x4080c801, 0xffe0ffc1, COD|RD_t|WR_C0, 0, M1|N5 }, -{"mtps", "t,P", 0x4080c800, 0xffe0ffc1, COD|RD_t|WR_C0, 0, M1|N5 }, -{"mtc0", "t,G", 0x40800000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC, 0, I1 }, -{"mtc0", "t,+D", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I32 }, -{"mtc0", "t,G,H", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I32 }, -{"mtc1", "t,S", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, 0, I1 }, -{"mtc1", "t,G", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, 0, I1 }, -{"mthc1", "t,S", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I33 }, -{"mthc1", "t,G", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I33 }, -/* mtc2 is at the bottom of the table. */ -/* mthc2 is at the bottom of the table. */ -/* mtc3 is at the bottom of the table. */ -{"mtdr", "t,G", 0x7080003d, 0xffe007ff, COD|RD_t|WR_C0, 0, N5 }, -{"mthi", "s", 0x00000011, 0xfc1fffff, RD_s|WR_HI, 0, I1 }, -{"mthi", "s,7", 0x00000011, 0xfc1fe7ff, RD_s|WR_HI, 0, D32 }, -{"mtlo", "s", 0x00000013, 0xfc1fffff, RD_s|WR_LO, 0, I1 }, -{"mtlo", "s,7", 0x00000013, 0xfc1fe7ff, RD_s|WR_LO, 0, D32 }, -{"mtlhx", "s", 0x00000053, 0xfc1fffff, RD_s|MOD_HILO, 0, SMT }, -{"mttc0", "t,G", 0x41800000, 0xffe007ff, TRAP|COD|RD_t|WR_C0|WR_CC, 0, MT32 }, -{"mttc0", "t,+D", 0x41800000, 0xffe007f8, TRAP|COD|RD_t|WR_C0|WR_CC, 0, MT32 }, -{"mttc0", "t,G,H", 0x41800000, 0xffe007f8, TRAP|COD|RD_t|WR_C0|WR_CC, 0, MT32 }, -{"mttc1", "t,S", 0x41800022, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_S, 0, MT32 }, -{"mttc1", "t,G", 0x41800022, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_S, 0, MT32 }, -{"mttc2", "t,g", 0x41800024, 0xffe007ff, TRAP|COD|RD_t|WR_C2|WR_CC, 0, MT32 }, -{"mttacx", "t", 0x41801021, 0xffe0ffff, TRAP|WR_a|RD_t, 0, MT32 }, -{"mttacx", "t,&", 0x41801021, 0xffe09fff, TRAP|WR_a|RD_t, 0, MT32 }, -{"mttdsp", "t", 0x41808021, 0xffe0ffff, TRAP|RD_t, 0, MT32 }, -{"mttgpr", "t,d", 0x41800020, 0xffe007ff, TRAP|WR_d|RD_t, 0, MT32 }, -{"mtthc1", "t,S", 0x41800032, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_D, 0, MT32 }, -{"mtthc1", "t,G", 0x41800032, 0xffe007ff, TRAP|COD|RD_t|WR_S|FP_D, 0, MT32 }, -{"mtthc2", "t,g", 0x41800034, 0xffe007ff, TRAP|COD|RD_t|WR_C2|WR_CC, 0, MT32 }, -{"mtthi", "t", 0x41800821, 0xffe0ffff, TRAP|WR_a|RD_t, 0, MT32 }, -{"mtthi", "t,&", 0x41800821, 0xffe09fff, TRAP|WR_a|RD_t, 0, MT32 }, -{"mttlo", "t", 0x41800021, 0xffe0ffff, TRAP|WR_a|RD_t, 0, MT32 }, -{"mttlo", "t,&", 0x41800021, 0xffe09fff, TRAP|WR_a|RD_t, 0, MT32 }, -{"mttr", "t,d,!,H,$", 0x41800000, 0xffe007c8, TRAP|RD_t, 0, MT32 }, -{"mul.d", "D,V,T", 0x46200002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, -{"mul.s", "D,V,T", 0x46000002, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, -{"mul.ob", "X,Y,Q", 0x78000030, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"mul.ob", "D,S,T", 0x4ac00030, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"mul.ob", "D,S,T[e]", 0x48000030, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"mul.ob", "D,S,k", 0x4bc00030, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"mul.ps", "D,V,T", 0x46c00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33|IL2F }, -{"mul.ps", "D,V,T", 0x45600002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"mul.qh", "X,Y,Q", 0x78200030, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"mul", "d,v,t", 0x70000002, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, I32|P3|N55}, -{"mul", "d,s,t", 0x00000058, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N54 }, -{"mul", "d,v,t", 0, (int) M_MUL, INSN_MACRO, 0, I1 }, -{"mul", "d,v,I", 0, (int) M_MUL_I, INSN_MACRO, 0, I1 }, -{"mula.ob", "Y,Q", 0x78000033, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"mula.ob", "S,T", 0x4ac00033, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mula.ob", "S,T[e]", 0x48000033, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mula.ob", "S,k", 0x4bc00033, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mula.qh", "Y,Q", 0x78200033, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"mulhi", "d,s,t", 0x00000258, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"mulhiu", "d,s,t", 0x00000259, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"mull.ob", "Y,Q", 0x78000433, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"mull.ob", "S,T", 0x4ac00433, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mull.ob", "S,T[e]", 0x48000433, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mull.ob", "S,k", 0x4bc00433, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mull.qh", "Y,Q", 0x78200433, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"mulo", "d,v,t", 0, (int) M_MULO, INSN_MACRO, 0, I1 }, -{"mulo", "d,v,I", 0, (int) M_MULO_I, INSN_MACRO, 0, I1 }, -{"mulou", "d,v,t", 0, (int) M_MULOU, INSN_MACRO, 0, I1 }, -{"mulou", "d,v,I", 0, (int) M_MULOU_I, INSN_MACRO, 0, I1 }, -{"mulr.ps", "D,S,T", 0x46c0001a, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, -{"muls", "d,s,t", 0x000000d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"mulsu", "d,s,t", 0x000000d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"mulshi", "d,s,t", 0x000002d8, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"mulshiu", "d,s,t", 0x000002d9, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"muls.ob", "Y,Q", 0x78000032, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"muls.ob", "S,T", 0x4ac00032, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"muls.ob", "S,T[e]", 0x48000032, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"muls.ob", "S,k", 0x4bc00032, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"muls.qh", "Y,Q", 0x78200032, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"mulsl.ob", "Y,Q", 0x78000432, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"mulsl.ob", "S,T", 0x4ac00432, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mulsl.ob", "S,T[e]", 0x48000432, 0xfe2007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mulsl.ob", "S,k", 0x4bc00432, 0xffe007ff, WR_CC|RD_S|RD_T, 0, N54 }, -{"mulsl.qh", "Y,Q", 0x78200432, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"mult", "s,t", 0x00000018, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, I1 }, -{"mult", "7,s,t", 0x00000018, 0xfc00e7ff, WR_a|RD_s|RD_t, 0, D33 }, -{"mult", "d,s,t", 0x00000018, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, -{"multp", "s,t", 0x00000459, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, SMT }, -{"multu", "s,t", 0x00000019, 0xfc00ffff, RD_s|RD_t|WR_HILO|IS_M, 0, I1 }, -{"multu", "7,s,t", 0x00000019, 0xfc00e7ff, WR_a|RD_s|RD_t, 0, D33 }, -{"multu", "d,s,t", 0x00000019, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d|IS_M, 0, G1 }, -{"mulu", "d,s,t", 0x00000059, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, -{"neg", "d,w", 0x00000022, 0xffe007ff, WR_d|RD_t, 0, I1 }, /* sub 0 */ -{"negu", "d,w", 0x00000023, 0xffe007ff, WR_d|RD_t, 0, I1 }, /* subu 0 */ -{"neg.d", "D,V", 0x46200007, 0xffff003f, WR_D|RD_S|FP_D, 0, I1 }, -{"neg.s", "D,V", 0x46000007, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 }, -{"neg.ps", "D,V", 0x46c00007, 0xffff003f, WR_D|RD_S|FP_D, 0, I5_33|IL2F }, -{"neg.ps", "D,V", 0x45600007, 0xffff003f, WR_D|RD_S|FP_D, 0, IL2E }, -{"nmadd.d", "D,R,S,T", 0x4c000031, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4_33 }, -{"nmadd.d", "D,S,T", 0x4620001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"nmadd.d", "D,S,T", 0x7220001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"nmadd.s", "D,R,S,T", 0x4c000030, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4_33 }, -{"nmadd.s", "D,S,T", 0x4600001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"nmadd.s", "D,S,T", 0x7200001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"nmadd.ps","D,R,S,T", 0x4c000036, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5_33 }, -{"nmadd.ps", "D,S,T", 0x4560001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"nmadd.ps", "D,S,T", 0x7160001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"nmsub.d", "D,R,S,T", 0x4c000039, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4_33 }, -{"nmsub.d", "D,S,T", 0x4620001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"nmsub.d", "D,S,T", 0x7220001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"nmsub.s", "D,R,S,T", 0x4c000038, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_S, 0, I4_33 }, -{"nmsub.s", "D,S,T", 0x4600001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"nmsub.s", "D,S,T", 0x7200001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"nmsub.ps","D,R,S,T", 0x4c00003e, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I5_33 }, -{"nmsub.ps", "D,S,T", 0x4560001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"nmsub.ps", "D,S,T", 0x7160001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -/* nop is at the start of the table. */ -{"nor", "d,v,t", 0x00000027, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"nor", "t,r,I", 0, (int) M_NOR_I, INSN_MACRO, 0, I1 }, -{"nor", "D,S,T", 0x47a00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"nor", "D,S,T", 0x4ba00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"nor.ob", "X,Y,Q", 0x7800000f, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"nor.ob", "D,S,T", 0x4ac0000f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"nor.ob", "D,S,T[e]", 0x4800000f, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"nor.ob", "D,S,k", 0x4bc0000f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"nor.qh", "X,Y,Q", 0x7820000f, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"not", "d,v", 0x00000027, 0xfc1f07ff, WR_d|RD_s|RD_t, 0, I1 },/*nor d,s,0*/ -{"or", "d,v,t", 0x00000025, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"or", "t,r,I", 0, (int) M_OR_I, INSN_MACRO, 0, I1 }, -{"or", "D,S,T", 0x45a00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"or", "D,S,T", 0x4b20000c, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"or.ob", "X,Y,Q", 0x7800000e, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"or.ob", "D,S,T", 0x4ac0000e, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"or.ob", "D,S,T[e]", 0x4800000e, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"or.ob", "D,S,k", 0x4bc0000e, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"or.qh", "X,Y,Q", 0x7820000e, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"ori", "t,r,i", 0x34000000, 0xfc000000, WR_t|RD_s, 0, I1 }, -{"pabsdiff.ob", "X,Y,Q",0x78000009, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, SB1 }, -{"pabsdiffc.ob", "Y,Q", 0x78000035, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, SB1 }, -{"pavg.ob", "X,Y,Q", 0x78000008, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, SB1 }, -{"pickf.ob", "X,Y,Q", 0x78000002, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"pickf.ob", "D,S,T", 0x4ac00002, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"pickf.ob", "D,S,T[e]",0x48000002, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"pickf.ob", "D,S,k", 0x4bc00002, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"pickf.qh", "X,Y,Q", 0x78200002, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"pickt.ob", "X,Y,Q", 0x78000003, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"pickt.ob", "D,S,T", 0x4ac00003, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"pickt.ob", "D,S,T[e]",0x48000003, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"pickt.ob", "D,S,k", 0x4bc00003, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"pickt.qh", "X,Y,Q", 0x78200003, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"pll.ps", "D,V,T", 0x46c0002c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33 }, -{"plu.ps", "D,V,T", 0x46c0002d, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33 }, - /* pref and prefx are at the start of the table. */ -{"pul.ps", "D,V,T", 0x46c0002e, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33 }, -{"puu.ps", "D,V,T", 0x46c0002f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33 }, -{"pperm", "s,t", 0x70000481, 0xfc00ffff, MOD_HILO|RD_s|RD_t, 0, SMT }, -{"rach.ob", "X", 0x7a00003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX|SB1 }, -{"rach.ob", "D", 0x4a00003f, 0xfffff83f, WR_D, 0, N54 }, -{"rach.qh", "X", 0x7a20003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX }, -{"racl.ob", "X", 0x7800003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX|SB1 }, -{"racl.ob", "D", 0x4800003f, 0xfffff83f, WR_D, 0, N54 }, -{"racl.qh", "X", 0x7820003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX }, -{"racm.ob", "X", 0x7900003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX|SB1 }, -{"racm.ob", "D", 0x4900003f, 0xfffff83f, WR_D, 0, N54 }, -{"racm.qh", "X", 0x7920003f, 0xfffff83f, WR_D|FP_D, RD_MACC, MX }, -{"recip.d", "D,S", 0x46200015, 0xffff003f, WR_D|RD_S|FP_D, 0, I4_33 }, -{"recip.ps","D,S", 0x46c00015, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 }, -{"recip.s", "D,S", 0x46000015, 0xffff003f, WR_D|RD_S|FP_S, 0, I4_33 }, -{"recip1.d", "D,S", 0x4620001d, 0xffff003f, WR_D|RD_S|FP_D, 0, M3D }, -{"recip1.ps", "D,S", 0x46c0001d, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, -{"recip1.s", "D,S", 0x4600001d, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, -{"recip2.d", "D,S,T", 0x4620001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, -{"recip2.ps", "D,S,T", 0x46c0001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, -{"recip2.s", "D,S,T", 0x4600001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, -{"rem", "z,s,t", 0x0000001a, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, -{"rem", "d,v,t", 0, (int) M_REM_3, INSN_MACRO, 0, I1 }, -{"rem", "d,v,I", 0, (int) M_REM_3I, INSN_MACRO, 0, I1 }, -{"remu", "z,s,t", 0x0000001b, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, I1 }, -{"remu", "d,v,t", 0, (int) M_REMU_3, INSN_MACRO, 0, I1 }, -{"remu", "d,v,I", 0, (int) M_REMU_3I, INSN_MACRO, 0, I1 }, -{"rdhwr", "t,K", 0x7c00003b, 0xffe007ff, WR_t, 0, I33 }, -{"rdpgpr", "d,w", 0x41400000, 0xffe007ff, WR_d, 0, I33 }, -{"rfe", "", 0x42000010, 0xffffffff, 0, 0, I1|T3 }, -{"rnas.qh", "X,Q", 0x78200025, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, -{"rnau.ob", "X,Q", 0x78000021, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX|SB1 }, -{"rnau.qh", "X,Q", 0x78200021, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, -{"rnes.qh", "X,Q", 0x78200026, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, -{"rneu.ob", "X,Q", 0x78000022, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX|SB1 }, -{"rneu.qh", "X,Q", 0x78200022, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, -{"rol", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I1 }, -{"rol", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I1 }, -{"ror", "d,v,t", 0, (int) M_ROR, INSN_MACRO, 0, I1 }, -{"ror", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, 0, I1 }, -{"ror", "d,w,<", 0x00200002, 0xffe0003f, WR_d|RD_t, 0, N5|I33|SMT }, -{"rorv", "d,t,s", 0x00000046, 0xfc0007ff, RD_t|RD_s|WR_d, 0, N5|I33|SMT }, -{"rotl", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I33|SMT }, -{"rotl", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I33|SMT }, -{"rotr", "d,v,t", 0, (int) M_ROR, INSN_MACRO, 0, I33|SMT }, -{"rotr", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, 0, I33|SMT }, -{"rotrv", "d,t,s", 0x00000046, 0xfc0007ff, RD_t|RD_s|WR_d, 0, I33|SMT }, -{"round.l.d", "D,S", 0x46200008, 0xffff003f, WR_D|RD_S|FP_D, 0, I3_33 }, -{"round.l.s", "D,S", 0x46000008, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3_33 }, -{"round.w.d", "D,S", 0x4620000c, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, -{"round.w.s", "D,S", 0x4600000c, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, -{"rsqrt.d", "D,S", 0x46200016, 0xffff003f, WR_D|RD_S|FP_D, 0, I4_33 }, -{"rsqrt.ps","D,S", 0x46c00016, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 }, -{"rsqrt.s", "D,S", 0x46000016, 0xffff003f, WR_D|RD_S|FP_S, 0, I4_33 }, -{"rsqrt1.d", "D,S", 0x4620001e, 0xffff003f, WR_D|RD_S|FP_D, 0, M3D }, -{"rsqrt1.ps", "D,S", 0x46c0001e, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, -{"rsqrt1.s", "D,S", 0x4600001e, 0xffff003f, WR_D|RD_S|FP_S, 0, M3D }, -{"rsqrt2.d", "D,S,T", 0x4620001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, M3D }, -{"rsqrt2.ps", "D,S,T", 0x46c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, -{"rsqrt2.s", "D,S,T", 0x4600001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, M3D }, -{"rzs.qh", "X,Q", 0x78200024, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, -{"rzu.ob", "X,Q", 0x78000020, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX|SB1 }, -{"rzu.ob", "D,k", 0x4bc00020, 0xffe0f83f, WR_D|RD_S|RD_T, 0, N54 }, -{"rzu.qh", "X,Q", 0x78200020, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, -{"sb", "t,o(b)", 0xa0000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, -{"sb", "t,A(b)", 0, (int) M_SB_AB, INSN_MACRO, 0, I1 }, -{"sc", "t,o(b)", 0xe0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I2 }, -{"sc", "t,A(b)", 0, (int) M_SC_AB, INSN_MACRO, 0, I2 }, -{"scd", "t,o(b)", 0xf0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I3 }, -{"scd", "t,A(b)", 0, (int) M_SCD_AB, INSN_MACRO, 0, I3 }, -{"sd", "t,o(b)", 0xfc000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 }, -{"sd", "t,o(b)", 0, (int) M_SD_OB, INSN_MACRO, 0, I1 }, -{"sd", "t,A(b)", 0, (int) M_SD_AB, INSN_MACRO, 0, I1 }, -{"sdbbp", "", 0x0000000e, 0xffffffff, TRAP, 0, G2 }, -{"sdbbp", "c", 0x0000000e, 0xfc00ffff, TRAP, 0, G2 }, -{"sdbbp", "c,q", 0x0000000e, 0xfc00003f, TRAP, 0, G2 }, -{"sdbbp", "", 0x7000003f, 0xffffffff, TRAP, 0, I32 }, -{"sdbbp", "B", 0x7000003f, 0xfc00003f, TRAP, 0, I32 }, -{"sdc1", "T,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, -{"sdc1", "E,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, -{"sdc1", "T,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, 0, I2 }, -{"sdc1", "E,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, 0, I2 }, -{"sdc2", "E,o(b)", 0xf8000000, 0xfc000000, SM|RD_C2|RD_b, 0, I2 }, -{"sdc2", "E,A(b)", 0, (int) M_SDC2_AB, INSN_MACRO, 0, I2 }, -{"sdc3", "E,o(b)", 0xfc000000, 0xfc000000, SM|RD_C3|RD_b, 0, I2 }, -{"sdc3", "E,A(b)", 0, (int) M_SDC3_AB, INSN_MACRO, 0, I2 }, -{"s.d", "T,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, -{"s.d", "T,o(b)", 0, (int) M_S_DOB, INSN_MACRO, 0, I1 }, -{"s.d", "T,A(b)", 0, (int) M_S_DAB, INSN_MACRO, 0, I1 }, -{"sdl", "t,o(b)", 0xb0000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 }, -{"sdl", "t,A(b)", 0, (int) M_SDL_AB, INSN_MACRO, 0, I3 }, -{"sdr", "t,o(b)", 0xb4000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 }, -{"sdr", "t,A(b)", 0, (int) M_SDR_AB, INSN_MACRO, 0, I3 }, -{"sdxc1", "S,t(b)", 0x4c000009, 0xfc0007ff, SM|RD_S|RD_t|RD_b|FP_D, 0, I4_33 }, -{"seb", "d,w", 0x7c000420, 0xffe007ff, WR_d|RD_t, 0, I33 }, -{"seh", "d,w", 0x7c000620, 0xffe007ff, WR_d|RD_t, 0, I33 }, -{"selsl", "d,v,t", 0x00000005, 0xfc0007ff, WR_d|RD_s|RD_t, 0, L1 }, -{"selsr", "d,v,t", 0x00000001, 0xfc0007ff, WR_d|RD_s|RD_t, 0, L1 }, -{"seq", "d,v,t", 0, (int) M_SEQ, INSN_MACRO, 0, I1 }, -{"seq", "d,v,I", 0, (int) M_SEQ_I, INSN_MACRO, 0, I1 }, -{"seq", "S,T", 0x46a00032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"seq", "S,T", 0x4ba0000c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"sge", "d,v,t", 0, (int) M_SGE, INSN_MACRO, 0, I1 }, -{"sge", "d,v,I", 0, (int) M_SGE_I, INSN_MACRO, 0, I1 }, -{"sgeu", "d,v,t", 0, (int) M_SGEU, INSN_MACRO, 0, I1 }, -{"sgeu", "d,v,I", 0, (int) M_SGEU_I, INSN_MACRO, 0, I1 }, -{"sgt", "d,v,t", 0, (int) M_SGT, INSN_MACRO, 0, I1 }, -{"sgt", "d,v,I", 0, (int) M_SGT_I, INSN_MACRO, 0, I1 }, -{"sgtu", "d,v,t", 0, (int) M_SGTU, INSN_MACRO, 0, I1 }, -{"sgtu", "d,v,I", 0, (int) M_SGTU_I, INSN_MACRO, 0, I1 }, -{"sh", "t,o(b)", 0xa4000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, -{"sh", "t,A(b)", 0, (int) M_SH_AB, INSN_MACRO, 0, I1 }, -{"shfl.bfla.qh", "X,Y,Z", 0x7a20001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"shfl.mixh.ob", "X,Y,Z", 0x7980001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"shfl.mixh.ob", "D,S,T", 0x4980001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"shfl.mixh.qh", "X,Y,Z", 0x7820001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"shfl.mixl.ob", "X,Y,Z", 0x79c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"shfl.mixl.ob", "D,S,T", 0x49c0001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"shfl.mixl.qh", "X,Y,Z", 0x78a0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"shfl.pach.ob", "X,Y,Z", 0x7900001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"shfl.pach.ob", "D,S,T", 0x4900001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"shfl.pach.qh", "X,Y,Z", 0x7920001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"shfl.pacl.ob", "D,S,T", 0x4940001f, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"shfl.repa.qh", "X,Y,Z", 0x7b20001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"shfl.repb.qh", "X,Y,Z", 0x7ba0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"shfl.upsl.ob", "X,Y,Z", 0x78c0001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"sle", "d,v,t", 0, (int) M_SLE, INSN_MACRO, 0, I1 }, -{"sle", "d,v,I", 0, (int) M_SLE_I, INSN_MACRO, 0, I1 }, -{"sle", "S,T", 0x46a0003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"sle", "S,T", 0x4ba0000e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"sleu", "d,v,t", 0, (int) M_SLEU, INSN_MACRO, 0, I1 }, -{"sleu", "d,v,I", 0, (int) M_SLEU_I, INSN_MACRO, 0, I1 }, -{"sleu", "S,T", 0x4680003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"sleu", "S,T", 0x4b80000e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"sllv", "d,t,s", 0x00000004, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, -{"sll", "d,w,s", 0x00000004, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, /* sllv */ -{"sll", "d,w,<", 0x00000000, 0xffe0003f, WR_d|RD_t, 0, I1 }, -{"sll", "D,S,T", 0x45800002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"sll", "D,S,T", 0x4b00000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"sll.ob", "X,Y,Q", 0x78000010, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"sll.ob", "D,S,T[e]", 0x48000010, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"sll.ob", "D,S,k", 0x4bc00010, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"sll.qh", "X,Y,Q", 0x78200010, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"slt", "d,v,t", 0x0000002a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"slt", "d,v,I", 0, (int) M_SLT_I, INSN_MACRO, 0, I1 }, -{"slt", "S,T", 0x46a0003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"slt", "S,T", 0x4ba0000d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"slti", "t,r,j", 0x28000000, 0xfc000000, WR_t|RD_s, 0, I1 }, -{"sltiu", "t,r,j", 0x2c000000, 0xfc000000, WR_t|RD_s, 0, I1 }, -{"sltu", "d,v,t", 0x0000002b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"sltu", "d,v,I", 0, (int) M_SLTU_I, INSN_MACRO, 0, I1 }, -{"sltu", "S,T", 0x4680003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"sltu", "S,T", 0x4b80000d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"sne", "d,v,t", 0, (int) M_SNE, INSN_MACRO, 0, I1 }, -{"sne", "d,v,I", 0, (int) M_SNE_I, INSN_MACRO, 0, I1 }, -{"sqrt.d", "D,S", 0x46200004, 0xffff003f, WR_D|RD_S|FP_D, 0, I2 }, -{"sqrt.s", "D,S", 0x46000004, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, -{"sqrt.ps", "D,S", 0x46c00004, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 }, -{"srav", "d,t,s", 0x00000007, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, -{"sra", "d,w,s", 0x00000007, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, /* srav */ -{"sra", "d,w,<", 0x00000003, 0xffe0003f, WR_d|RD_t, 0, I1 }, -{"sra", "D,S,T", 0x45c00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"sra", "D,S,T", 0x4b40000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"sra.qh", "X,Y,Q", 0x78200013, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"srlv", "d,t,s", 0x00000006, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, -{"srl", "d,w,s", 0x00000006, 0xfc0007ff, WR_d|RD_t|RD_s, 0, I1 }, /* srlv */ -{"srl", "d,w,<", 0x00000002, 0xffe0003f, WR_d|RD_t, 0, I1 }, -{"srl", "D,S,T", 0x45800003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"srl", "D,S,T", 0x4b00000f, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"srl.ob", "X,Y,Q", 0x78000012, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"srl.ob", "D,S,T[e]", 0x48000012, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"srl.ob", "D,S,k", 0x4bc00012, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"srl.qh", "X,Y,Q", 0x78200012, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -/* ssnop is at the start of the table. */ -{"standby", "", 0x42000021, 0xffffffff, 0, 0, V1 }, -{"sub", "d,v,t", 0x00000022, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"sub", "d,v,I", 0, (int) M_SUB_I, INSN_MACRO, 0, I1 }, -{"sub", "D,S,T", 0x45c00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"sub", "D,S,T", 0x4b40000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"sub.d", "D,V,T", 0x46200001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I1 }, -{"sub.s", "D,V,T", 0x46000001, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I1 }, -{"sub.ob", "X,Y,Q", 0x7800000a, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"sub.ob", "D,S,T", 0x4ac0000a, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"sub.ob", "D,S,T[e]", 0x4800000a, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"sub.ob", "D,S,k", 0x4bc0000a, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"sub.ps", "D,V,T", 0x46c00001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I5_33|IL2F }, -{"sub.ps", "D,V,T", 0x45600001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"sub.qh", "X,Y,Q", 0x7820000a, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"suba.ob", "Y,Q", 0x78000036, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"suba.qh", "Y,Q", 0x78200036, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"subl.ob", "Y,Q", 0x78000436, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"subl.qh", "Y,Q", 0x78200436, 0xfc2007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"subu", "d,v,t", 0x00000023, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"subu", "d,v,I", 0, (int) M_SUBU_I, INSN_MACRO, 0, I1 }, -{"subu", "D,S,T", 0x45800001, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2E }, -{"subu", "D,S,T", 0x4b00000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_S, 0, IL2F }, -{"suspend", "", 0x42000022, 0xffffffff, 0, 0, V1 }, -{"suxc1", "S,t(b)", 0x4c00000d, 0xfc0007ff, SM|RD_S|RD_t|RD_b, 0, I5_33|N55}, -{"sw", "t,o(b)", 0xac000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, -{"sw", "t,A(b)", 0, (int) M_SW_AB, INSN_MACRO, 0, I1 }, -{"swc0", "E,o(b)", 0xe0000000, 0xfc000000, SM|RD_C0|RD_b, 0, I1 }, -{"swc0", "E,A(b)", 0, (int) M_SWC0_AB, INSN_MACRO, 0, I1 }, -{"swc1", "T,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, 0, I1 }, -{"swc1", "E,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, 0, I1 }, -{"swc1", "T,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, 0, I1 }, -{"swc1", "E,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, 0, I1 }, -{"s.s", "T,o(b)", 0xe4000000, 0xfc000000, SM|RD_T|RD_b|FP_S, 0, I1 }, /* swc1 */ -{"s.s", "T,A(b)", 0, (int) M_SWC1_AB, INSN_MACRO, 0, I1 }, -{"swc2", "E,o(b)", 0xe8000000, 0xfc000000, SM|RD_C2|RD_b, 0, I1 }, -{"swc2", "E,A(b)", 0, (int) M_SWC2_AB, INSN_MACRO, 0, I1 }, -{"swc3", "E,o(b)", 0xec000000, 0xfc000000, SM|RD_C3|RD_b, 0, I1 }, -{"swc3", "E,A(b)", 0, (int) M_SWC3_AB, INSN_MACRO, 0, I1 }, -{"swl", "t,o(b)", 0xa8000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, -{"swl", "t,A(b)", 0, (int) M_SWL_AB, INSN_MACRO, 0, I1 }, -{"scache", "t,o(b)", 0xa8000000, 0xfc000000, RD_t|RD_b, 0, I2 }, /* same */ -{"scache", "t,A(b)", 0, (int) M_SWL_AB, INSN_MACRO, 0, I2 }, /* as swl */ -{"swr", "t,o(b)", 0xb8000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, -{"swr", "t,A(b)", 0, (int) M_SWR_AB, INSN_MACRO, 0, I1 }, -{"invalidate", "t,o(b)",0xb8000000, 0xfc000000, RD_t|RD_b, 0, I2 }, /* same */ -{"invalidate", "t,A(b)",0, (int) M_SWR_AB, INSN_MACRO, 0, I2 }, /* as swr */ -{"swxc1", "S,t(b)", 0x4c000008, 0xfc0007ff, SM|RD_S|RD_t|RD_b|FP_S, 0, I4_33 }, -{"sync", "", 0x0000000f, 0xffffffff, INSN_SYNC, 0, I2|G1 }, -{"sync.p", "", 0x0000040f, 0xffffffff, INSN_SYNC, 0, I2 }, -{"sync.l", "", 0x0000000f, 0xffffffff, INSN_SYNC, 0, I2 }, -{"synci", "o(b)", 0x041f0000, 0xfc1f0000, SM|RD_b, 0, I33 }, -{"synciobdma", "", 0x0000008f, 0xffffffff, INSN_SYNC, 0, IOCT }, -{"syscall", "", 0x0000000c, 0xffffffff, TRAP, 0, I1 }, -{"syscall", "B", 0x0000000c, 0xfc00003f, TRAP, 0, I1 }, -{"teqi", "s,j", 0x040c0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, -{"teq", "s,t", 0x00000034, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, -{"teq", "s,t,q", 0x00000034, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, -{"teq", "s,j", 0x040c0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* teqi */ -{"teq", "s,I", 0, (int) M_TEQ_I, INSN_MACRO, 0, I2 }, -{"tgei", "s,j", 0x04080000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, -{"tge", "s,t", 0x00000030, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, -{"tge", "s,t,q", 0x00000030, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, -{"tge", "s,j", 0x04080000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tgei */ -{"tge", "s,I", 0, (int) M_TGE_I, INSN_MACRO, 0, I2 }, -{"tgeiu", "s,j", 0x04090000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, -{"tgeu", "s,t", 0x00000031, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, -{"tgeu", "s,t,q", 0x00000031, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, -{"tgeu", "s,j", 0x04090000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tgeiu */ -{"tgeu", "s,I", 0, (int) M_TGEU_I, INSN_MACRO, 0, I2 }, -{"tlbp", "", 0x42000008, 0xffffffff, INSN_TLB, 0, I1 }, -{"tlbr", "", 0x42000001, 0xffffffff, INSN_TLB, 0, I1 }, -{"tlbwi", "", 0x42000002, 0xffffffff, INSN_TLB, 0, I1 }, -{"tlbwr", "", 0x42000006, 0xffffffff, INSN_TLB, 0, I1 }, -{"tlti", "s,j", 0x040a0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, -{"tlt", "s,t", 0x00000032, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, -{"tlt", "s,t,q", 0x00000032, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, -{"tlt", "s,j", 0x040a0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tlti */ -{"tlt", "s,I", 0, (int) M_TLT_I, INSN_MACRO, 0, I2 }, -{"tltiu", "s,j", 0x040b0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, -{"tltu", "s,t", 0x00000033, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, -{"tltu", "s,t,q", 0x00000033, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, -{"tltu", "s,j", 0x040b0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tltiu */ -{"tltu", "s,I", 0, (int) M_TLTU_I, INSN_MACRO, 0, I2 }, -{"tnei", "s,j", 0x040e0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, -{"tne", "s,t", 0x00000036, 0xfc00ffff, RD_s|RD_t|TRAP, 0, I2 }, -{"tne", "s,t,q", 0x00000036, 0xfc00003f, RD_s|RD_t|TRAP, 0, I2 }, -{"tne", "s,j", 0x040e0000, 0xfc1f0000, RD_s|TRAP, 0, I2 }, /* tnei */ -{"tne", "s,I", 0, (int) M_TNE_I, INSN_MACRO, 0, I2 }, -{"trunc.l.d", "D,S", 0x46200009, 0xffff003f, WR_D|RD_S|FP_D, 0, I3_33 }, -{"trunc.l.s", "D,S", 0x46000009, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3_33 }, -{"trunc.w.d", "D,S", 0x4620000d, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, -{"trunc.w.d", "D,S,x", 0x4620000d, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, -{"trunc.w.d", "D,S,t", 0, (int) M_TRUNCWD, INSN_MACRO, 0, I1 }, -{"trunc.w.s", "D,S", 0x4600000d, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, -{"trunc.w.s", "D,S,x", 0x4600000d, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, -{"trunc.w.s", "D,S,t", 0, (int) M_TRUNCWS, INSN_MACRO, 0, I1 }, -{"uld", "t,o(b)", 0, (int) M_ULD, INSN_MACRO, 0, I3 }, -{"uld", "t,A(b)", 0, (int) M_ULD_A, INSN_MACRO, 0, I3 }, -{"ulh", "t,o(b)", 0, (int) M_ULH, INSN_MACRO, 0, I1 }, -{"ulh", "t,A(b)", 0, (int) M_ULH_A, INSN_MACRO, 0, I1 }, -{"ulhu", "t,o(b)", 0, (int) M_ULHU, INSN_MACRO, 0, I1 }, -{"ulhu", "t,A(b)", 0, (int) M_ULHU_A, INSN_MACRO, 0, I1 }, -{"ulw", "t,o(b)", 0, (int) M_ULW, INSN_MACRO, 0, I1 }, -{"ulw", "t,A(b)", 0, (int) M_ULW_A, INSN_MACRO, 0, I1 }, -{"usd", "t,o(b)", 0, (int) M_USD, INSN_MACRO, 0, I3 }, -{"usd", "t,A(b)", 0, (int) M_USD_A, INSN_MACRO, 0, I3 }, -{"ush", "t,o(b)", 0, (int) M_USH, INSN_MACRO, 0, I1 }, -{"ush", "t,A(b)", 0, (int) M_USH_A, INSN_MACRO, 0, I1 }, -{"usw", "t,o(b)", 0, (int) M_USW, INSN_MACRO, 0, I1 }, -{"usw", "t,A(b)", 0, (int) M_USW_A, INSN_MACRO, 0, I1 }, -{"wach.ob", "Y", 0x7a00003e, 0xffff07ff, RD_S|FP_D, WR_MACC, MX|SB1 }, -{"wach.ob", "S", 0x4a00003e, 0xffff07ff, RD_S, 0, N54 }, -{"wach.qh", "Y", 0x7a20003e, 0xffff07ff, RD_S|FP_D, WR_MACC, MX }, -{"wacl.ob", "Y,Z", 0x7800003e, 0xffe007ff, RD_S|RD_T|FP_D, WR_MACC, MX|SB1 }, -{"wacl.ob", "S,T", 0x4800003e, 0xffe007ff, RD_S|RD_T, 0, N54 }, -{"wacl.qh", "Y,Z", 0x7820003e, 0xffe007ff, RD_S|RD_T|FP_D, WR_MACC, MX }, -{"wait", "", 0x42000020, 0xffffffff, TRAP, 0, I3_32 }, -{"wait", "J", 0x42000020, 0xfe00003f, TRAP, 0, I32|N55 }, -{"waiti", "", 0x42000020, 0xffffffff, TRAP, 0, L1 }, -{"wrpgpr", "d,w", 0x41c00000, 0xffe007ff, RD_t, 0, I33 }, -{"wsbh", "d,w", 0x7c0000a0, 0xffe007ff, WR_d|RD_t, 0, I33 }, -{"xor", "d,v,t", 0x00000026, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 }, -{"xor", "t,r,I", 0, (int) M_XOR_I, INSN_MACRO, 0, I1 }, -{"xor", "D,S,T", 0x47800002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"xor", "D,S,T", 0x4b800002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"xor.ob", "X,Y,Q", 0x7800000d, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX|SB1 }, -{"xor.ob", "D,S,T", 0x4ac0000d, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"xor.ob", "D,S,T[e]", 0x4800000d, 0xfe20003f, WR_D|RD_S|RD_T, 0, N54 }, -{"xor.ob", "D,S,k", 0x4bc0000d, 0xffe0003f, WR_D|RD_S|RD_T, 0, N54 }, -{"xor.qh", "X,Y,Q", 0x7820000d, 0xfc20003f, WR_D|RD_S|RD_T|FP_D, 0, MX }, -{"xori", "t,r,i", 0x38000000, 0xfc000000, WR_t|RD_s, 0, I1 }, -{"yield", "s", 0x7c000009, 0xfc1fffff, TRAP|RD_s, 0, MT32 }, -{"yield", "d,s", 0x7c000009, 0xfc1f07ff, TRAP|WR_d|RD_s, 0, MT32 }, - -/* User Defined Instruction. */ -{"udi0", "s,t,d,+1",0x70000010, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi0", "s,t,+2", 0x70000010, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi0", "s,+3", 0x70000010, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi0", "+4", 0x70000010, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi1", "s,t,d,+1",0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi1", "s,t,+2", 0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi1", "s,+3", 0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi1", "+4", 0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi2", "s,t,d,+1",0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi2", "s,t,+2", 0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi2", "s,+3", 0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi2", "+4", 0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi3", "s,t,d,+1",0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi3", "s,t,+2", 0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi3", "s,+3", 0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi3", "+4", 0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi4", "s,t,d,+1",0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi4", "s,t,+2", 0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi4", "s,+3", 0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi4", "+4", 0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi5", "s,t,d,+1",0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi5", "s,t,+2", 0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi5", "s,+3", 0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi5", "+4", 0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi6", "s,t,d,+1",0x70000016, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi6", "s,t,+2", 0x70000016, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi6", "s,+3", 0x70000016, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi6", "+4", 0x70000016, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi7", "s,t,d,+1",0x70000017, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi7", "s,t,+2", 0x70000017, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi7", "s,+3", 0x70000017, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi7", "+4", 0x70000017, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi8", "s,t,d,+1",0x70000018, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi8", "s,t,+2", 0x70000018, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi8", "s,+3", 0x70000018, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi8", "+4", 0x70000018, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi9", "s,t,d,+1",0x70000019, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi9", "s,t,+2", 0x70000019, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi9", "s,+3", 0x70000019, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi9", "+4", 0x70000019, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi10", "s,t,d,+1",0x7000001a, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi10", "s,t,+2", 0x7000001a, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi10", "s,+3", 0x7000001a, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi10", "+4", 0x7000001a, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi11", "s,t,d,+1",0x7000001b, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi11", "s,t,+2", 0x7000001b, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi11", "s,+3", 0x7000001b, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi11", "+4", 0x7000001b, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi12", "s,t,d,+1",0x7000001c, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi12", "s,t,+2", 0x7000001c, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi12", "s,+3", 0x7000001c, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi12", "+4", 0x7000001c, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi13", "s,t,d,+1",0x7000001d, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi13", "s,t,+2", 0x7000001d, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi13", "s,+3", 0x7000001d, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi13", "+4", 0x7000001d, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi14", "s,t,d,+1",0x7000001e, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi14", "s,t,+2", 0x7000001e, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi14", "s,+3", 0x7000001e, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi14", "+4", 0x7000001e, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi15", "s,t,d,+1",0x7000001f, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi15", "s,t,+2", 0x7000001f, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi15", "s,+3", 0x7000001f, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, -{"udi15", "+4", 0x7000001f, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, - -/* Coprocessor 2 move/branch operations overlap with VR5400 .ob format - instructions so they are here for the latters to take precedence. */ -{"bc2f", "p", 0x49000000, 0xffff0000, CBD|RD_CC, 0, I1 }, -{"bc2f", "N,p", 0x49000000, 0xffe30000, CBD|RD_CC, 0, I32 }, -{"bc2fl", "p", 0x49020000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, -{"bc2fl", "N,p", 0x49020000, 0xffe30000, CBL|RD_CC, 0, I32 }, -{"bc2t", "p", 0x49010000, 0xffff0000, CBD|RD_CC, 0, I1 }, -{"bc2t", "N,p", 0x49010000, 0xffe30000, CBD|RD_CC, 0, I32 }, -{"bc2tl", "p", 0x49030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, -{"bc2tl", "N,p", 0x49030000, 0xffe30000, CBL|RD_CC, 0, I32 }, -{"cfc2", "t,G", 0x48400000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1 }, -{"ctc2", "t,G", 0x48c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, -{"dmfc2", "t,G", 0x48200000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I3 }, -{"dmfc2", "t,G,H", 0x48200000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I64 }, -{"dmtc2", "t,G", 0x48a00000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I3 }, -{"dmtc2", "t,G,H", 0x48a00000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I64 }, -{"mfc2", "t,G", 0x48000000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1 }, -{"mfc2", "t,G,H", 0x48000000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I32 }, -{"mfhc2", "t,G", 0x48600000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I33 }, -{"mfhc2", "t,G,H", 0x48600000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I33 }, -{"mfhc2", "t,i", 0x48600000, 0xffe00000, LCD|WR_t|RD_C2, 0, I33 }, -{"mtc2", "t,G", 0x48800000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I1 }, -{"mtc2", "t,G,H", 0x48800000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I32 }, -{"mthc2", "t,G", 0x48e00000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I33 }, -{"mthc2", "t,G,H", 0x48e00000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I33 }, -{"mthc2", "t,i", 0x48e00000, 0xffe00000, COD|RD_t|WR_C2|WR_CC, 0, I33 }, - -/* Coprocessor 3 move/branch operations overlap with MIPS IV COP1X - instructions, so they are here for the latters to take precedence. */ -{"bc3f", "p", 0x4d000000, 0xffff0000, CBD|RD_CC, 0, I1 }, -{"bc3fl", "p", 0x4d020000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, -{"bc3t", "p", 0x4d010000, 0xffff0000, CBD|RD_CC, 0, I1 }, -{"bc3tl", "p", 0x4d030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, -{"cfc3", "t,G", 0x4c400000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I1 }, -{"ctc3", "t,G", 0x4cc00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, -{"dmfc3", "t,G", 0x4c200000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I3 }, -{"dmtc3", "t,G", 0x4ca00000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, 0, I3 }, -{"mfc3", "t,G", 0x4c000000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I1 }, -{"mfc3", "t,G,H", 0x4c000000, 0xffe007f8, LCD|WR_t|RD_C3, 0, I32 }, -{"mtc3", "t,G", 0x4c800000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, 0, I1 }, -{"mtc3", "t,G,H", 0x4c800000, 0xffe007f8, COD|RD_t|WR_C3|WR_CC, 0, I32 }, - - /* Conflicts with the 4650's "mul" instruction. Nobody's using the - 4010 any more, so move this insn out of the way. If the object - format gave us more info, we could do this right. */ -{"addciu", "t,r,j", 0x70000000, 0xfc000000, WR_t|RD_s, 0, L1 }, -/* MIPS DSP ASE */ -{"absq_s.ph", "d,t", 0x7c000252, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"absq_s.pw", "d,t", 0x7c000456, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"absq_s.qh", "d,t", 0x7c000256, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"absq_s.w", "d,t", 0x7c000452, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"addq.ph", "d,s,t", 0x7c000290, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"addq.pw", "d,s,t", 0x7c000494, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"addq.qh", "d,s,t", 0x7c000294, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"addq_s.ph", "d,s,t", 0x7c000390, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"addq_s.pw", "d,s,t", 0x7c000594, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"addq_s.qh", "d,s,t", 0x7c000394, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"addq_s.w", "d,s,t", 0x7c000590, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"addsc", "d,s,t", 0x7c000410, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"addu.ob", "d,s,t", 0x7c000014, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"addu.qb", "d,s,t", 0x7c000010, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"addu_s.ob", "d,s,t", 0x7c000114, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"addu_s.qb", "d,s,t", 0x7c000110, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"addwc", "d,s,t", 0x7c000450, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"bitrev", "d,t", 0x7c0006d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"bposge32", "p", 0x041c0000, 0xffff0000, CBD, 0, D32 }, -{"bposge64", "p", 0x041d0000, 0xffff0000, CBD, 0, D64 }, -{"cmp.eq.ph", "s,t", 0x7c000211, 0xfc00ffff, RD_s|RD_t, 0, D32 }, -{"cmp.eq.pw", "s,t", 0x7c000415, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmp.eq.qh", "s,t", 0x7c000215, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmpgu.eq.ob", "d,s,t", 0x7c000115, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"cmpgu.eq.qb", "d,s,t", 0x7c000111, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"cmpgu.le.ob", "d,s,t", 0x7c000195, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"cmpgu.le.qb", "d,s,t", 0x7c000191, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"cmpgu.lt.ob", "d,s,t", 0x7c000155, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"cmpgu.lt.qb", "d,s,t", 0x7c000151, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"cmp.le.ph", "s,t", 0x7c000291, 0xfc00ffff, RD_s|RD_t, 0, D32 }, -{"cmp.le.pw", "s,t", 0x7c000495, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmp.le.qh", "s,t", 0x7c000295, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmp.lt.ph", "s,t", 0x7c000251, 0xfc00ffff, RD_s|RD_t, 0, D32 }, -{"cmp.lt.pw", "s,t", 0x7c000455, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmp.lt.qh", "s,t", 0x7c000255, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmpu.eq.ob", "s,t", 0x7c000015, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmpu.eq.qb", "s,t", 0x7c000011, 0xfc00ffff, RD_s|RD_t, 0, D32 }, -{"cmpu.le.ob", "s,t", 0x7c000095, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmpu.le.qb", "s,t", 0x7c000091, 0xfc00ffff, RD_s|RD_t, 0, D32 }, -{"cmpu.lt.ob", "s,t", 0x7c000055, 0xfc00ffff, RD_s|RD_t, 0, D64 }, -{"cmpu.lt.qb", "s,t", 0x7c000051, 0xfc00ffff, RD_s|RD_t, 0, D32 }, -{"dextpdp", "t,7,6", 0x7c0002bc, 0xfc00e7ff, WR_t|RD_a|DSP_VOLA, 0, D64 }, -{"dextpdpv", "t,7,s", 0x7c0002fc, 0xfc00e7ff, WR_t|RD_a|RD_s|DSP_VOLA, 0, D64 }, -{"dextp", "t,7,6", 0x7c0000bc, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dextpv", "t,7,s", 0x7c0000fc, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextr.l", "t,7,6", 0x7c00043c, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dextr_r.l", "t,7,6", 0x7c00053c, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dextr_rs.l", "t,7,6", 0x7c0005bc, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dextr_rs.w", "t,7,6", 0x7c0001bc, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dextr_r.w", "t,7,6", 0x7c00013c, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dextr_s.h", "t,7,6", 0x7c0003bc, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dextrv.l", "t,7,s", 0x7c00047c, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextrv_r.l", "t,7,s", 0x7c00057c, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextrv_rs.l", "t,7,s", 0x7c0005fc, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextrv_rs.w", "t,7,s", 0x7c0001fc, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextrv_r.w", "t,7,s", 0x7c00017c, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextrv_s.h", "t,7,s", 0x7c0003fc, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextrv.w", "t,7,s", 0x7c00007c, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D64 }, -{"dextr.w", "t,7,6", 0x7c00003c, 0xfc00e7ff, WR_t|RD_a, 0, D64 }, -{"dinsv", "t,s", 0x7c00000d, 0xfc00ffff, WR_t|RD_s, 0, D64 }, -{"dmadd", "7,s,t", 0x7c000674, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dmaddu", "7,s,t", 0x7c000774, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dmsub", "7,s,t", 0x7c0006f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dmsubu", "7,s,t", 0x7c0007f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dmthlip", "s,7", 0x7c0007fc, 0xfc1fe7ff, RD_s|MOD_a|DSP_VOLA, 0, D64 }, -{"dpaq_sa.l.pw", "7,s,t", 0x7c000334, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpaq_sa.l.w", "7,s,t", 0x7c000330, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dpaq_s.w.ph", "7,s,t", 0x7c000130, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dpaq_s.w.qh", "7,s,t", 0x7c000134, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpau.h.obl", "7,s,t", 0x7c0000f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpau.h.obr", "7,s,t", 0x7c0001f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpau.h.qbl", "7,s,t", 0x7c0000f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dpau.h.qbr", "7,s,t", 0x7c0001f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dpsq_sa.l.pw", "7,s,t", 0x7c000374, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpsq_sa.l.w", "7,s,t", 0x7c000370, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dpsq_s.w.ph", "7,s,t", 0x7c000170, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dpsq_s.w.qh", "7,s,t", 0x7c000174, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpsu.h.obl", "7,s,t", 0x7c0002f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpsu.h.obr", "7,s,t", 0x7c0003f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"dpsu.h.qbl", "7,s,t", 0x7c0002f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dpsu.h.qbr", "7,s,t", 0x7c0003f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"dshilo", "7,:", 0x7c0006bc, 0xfc07e7ff, MOD_a, 0, D64 }, -{"dshilov", "7,s", 0x7c0006fc, 0xfc1fe7ff, MOD_a|RD_s, 0, D64 }, -{"extpdp", "t,7,6", 0x7c0002b8, 0xfc00e7ff, WR_t|RD_a|DSP_VOLA, 0, D32 }, -{"extpdpv", "t,7,s", 0x7c0002f8, 0xfc00e7ff, WR_t|RD_a|RD_s|DSP_VOLA, 0, D32 }, -{"extp", "t,7,6", 0x7c0000b8, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, -{"extpv", "t,7,s", 0x7c0000f8, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, -{"extr_rs.w", "t,7,6", 0x7c0001b8, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, -{"extr_r.w", "t,7,6", 0x7c000138, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, -{"extr_s.h", "t,7,6", 0x7c0003b8, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, -{"extrv_rs.w", "t,7,s", 0x7c0001f8, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, -{"extrv_r.w", "t,7,s", 0x7c000178, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, -{"extrv_s.h", "t,7,s", 0x7c0003f8, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, -{"extrv.w", "t,7,s", 0x7c000078, 0xfc00e7ff, WR_t|RD_a|RD_s, 0, D32 }, -{"extr.w", "t,7,6", 0x7c000038, 0xfc00e7ff, WR_t|RD_a, 0, D32 }, -{"insv", "t,s", 0x7c00000c, 0xfc00ffff, WR_t|RD_s, 0, D32 }, -{"lbux", "d,t(b)", 0x7c00018a, 0xfc0007ff, LDD|WR_d|RD_t|RD_b, 0, D32 }, -{"ldx", "d,t(b)", 0x7c00020a, 0xfc0007ff, LDD|WR_d|RD_t|RD_b, 0, D64 }, -{"lhx", "d,t(b)", 0x7c00010a, 0xfc0007ff, LDD|WR_d|RD_t|RD_b, 0, D32 }, -{"lwx", "d,t(b)", 0x7c00000a, 0xfc0007ff, LDD|WR_d|RD_t|RD_b, 0, D32 }, -{"maq_sa.w.phl", "7,s,t", 0x7c000430, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"maq_sa.w.phr", "7,s,t", 0x7c0004b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"maq_sa.w.qhll", "7,s,t", 0x7c000434, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_sa.w.qhlr", "7,s,t", 0x7c000474, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_sa.w.qhrl", "7,s,t", 0x7c0004b4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_sa.w.qhrr", "7,s,t", 0x7c0004f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_s.l.pwl", "7,s,t", 0x7c000734, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_s.l.pwr", "7,s,t", 0x7c0007b4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_s.w.phl", "7,s,t", 0x7c000530, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"maq_s.w.phr", "7,s,t", 0x7c0005b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"maq_s.w.qhll", "7,s,t", 0x7c000534, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_s.w.qhlr", "7,s,t", 0x7c000574, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_s.w.qhrl", "7,s,t", 0x7c0005b4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"maq_s.w.qhrr", "7,s,t", 0x7c0005f4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"modsub", "d,s,t", 0x7c000490, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"mthlip", "s,7", 0x7c0007f8, 0xfc1fe7ff, RD_s|MOD_a|DSP_VOLA, 0, D32 }, -{"muleq_s.pw.qhl", "d,s,t", 0x7c000714, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D64 }, -{"muleq_s.pw.qhr", "d,s,t", 0x7c000754, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D64 }, -{"muleq_s.w.phl", "d,s,t", 0x7c000710, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, -{"muleq_s.w.phr", "d,s,t", 0x7c000750, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, -{"muleu_s.ph.qbl", "d,s,t", 0x7c000190, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, -{"muleu_s.ph.qbr", "d,s,t", 0x7c0001d0, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, -{"muleu_s.qh.obl", "d,s,t", 0x7c000194, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D64 }, -{"muleu_s.qh.obr", "d,s,t", 0x7c0001d4, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D64 }, -{"mulq_rs.ph", "d,s,t", 0x7c0007d0, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D32 }, -{"mulq_rs.qh", "d,s,t", 0x7c0007d4, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D64 }, -{"mulsaq_s.l.pw", "7,s,t", 0x7c0003b4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"mulsaq_s.w.ph", "7,s,t", 0x7c0001b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D32 }, -{"mulsaq_s.w.qh", "7,s,t", 0x7c0001b4, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D64 }, -{"packrl.ph", "d,s,t", 0x7c000391, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"packrl.pw", "d,s,t", 0x7c000395, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"pick.ob", "d,s,t", 0x7c0000d5, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"pick.ph", "d,s,t", 0x7c0002d1, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"pick.pw", "d,s,t", 0x7c0004d5, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"pick.qb", "d,s,t", 0x7c0000d1, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"pick.qh", "d,s,t", 0x7c0002d5, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"preceq.pw.qhla", "d,t", 0x7c000396, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceq.pw.qhl", "d,t", 0x7c000316, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceq.pw.qhra", "d,t", 0x7c0003d6, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceq.pw.qhr", "d,t", 0x7c000356, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceq.s.l.pwl", "d,t", 0x7c000516, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceq.s.l.pwr", "d,t", 0x7c000556, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"precequ.ph.qbla", "d,t", 0x7c000192, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"precequ.ph.qbl", "d,t", 0x7c000112, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"precequ.ph.qbra", "d,t", 0x7c0001d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"precequ.ph.qbr", "d,t", 0x7c000152, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"precequ.pw.qhla", "d,t", 0x7c000196, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"precequ.pw.qhl", "d,t", 0x7c000116, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"precequ.pw.qhra", "d,t", 0x7c0001d6, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"precequ.pw.qhr", "d,t", 0x7c000156, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceq.w.phl", "d,t", 0x7c000312, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"preceq.w.phr", "d,t", 0x7c000352, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"preceu.ph.qbla", "d,t", 0x7c000792, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"preceu.ph.qbl", "d,t", 0x7c000712, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"preceu.ph.qbra", "d,t", 0x7c0007d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"preceu.ph.qbr", "d,t", 0x7c000752, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"preceu.qh.obla", "d,t", 0x7c000796, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceu.qh.obl", "d,t", 0x7c000716, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceu.qh.obra", "d,t", 0x7c0007d6, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"preceu.qh.obr", "d,t", 0x7c000756, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"precrq.ob.qh", "d,s,t", 0x7c000315, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"precrq.ph.w", "d,s,t", 0x7c000511, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"precrq.pw.l", "d,s,t", 0x7c000715, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"precrq.qb.ph", "d,s,t", 0x7c000311, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"precrq.qh.pw", "d,s,t", 0x7c000515, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"precrq_rs.ph.w", "d,s,t", 0x7c000551, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"precrq_rs.qh.pw", "d,s,t", 0x7c000555, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"precrqu_s.ob.qh", "d,s,t", 0x7c0003d5, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"precrqu_s.qb.ph", "d,s,t", 0x7c0003d1, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"raddu.l.ob", "d,s", 0x7c000514, 0xfc1f07ff, WR_d|RD_s, 0, D64 }, -{"raddu.w.qb", "d,s", 0x7c000510, 0xfc1f07ff, WR_d|RD_s, 0, D32 }, -{"rddsp", "d", 0x7fff04b8, 0xffff07ff, WR_d, 0, D32 }, -{"rddsp", "d,'", 0x7c0004b8, 0xffc007ff, WR_d, 0, D32 }, -{"repl.ob", "d,5", 0x7c000096, 0xff0007ff, WR_d, 0, D64 }, -{"repl.ph", "d,@", 0x7c000292, 0xfc0007ff, WR_d, 0, D32 }, -{"repl.pw", "d,@", 0x7c000496, 0xfc0007ff, WR_d, 0, D64 }, -{"repl.qb", "d,5", 0x7c000092, 0xff0007ff, WR_d, 0, D32 }, -{"repl.qh", "d,@", 0x7c000296, 0xfc0007ff, WR_d, 0, D64 }, -{"replv.ob", "d,t", 0x7c0000d6, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"replv.ph", "d,t", 0x7c0002d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"replv.pw", "d,t", 0x7c0004d6, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"replv.qb", "d,t", 0x7c0000d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, -{"replv.qh", "d,t", 0x7c0002d6, 0xffe007ff, WR_d|RD_t, 0, D64 }, -{"shilo", "7,0", 0x7c0006b8, 0xfc0fe7ff, MOD_a, 0, D32 }, -{"shilov", "7,s", 0x7c0006f8, 0xfc1fe7ff, MOD_a|RD_s, 0, D32 }, -{"shll.ob", "d,t,3", 0x7c000017, 0xff0007ff, WR_d|RD_t, 0, D64 }, -{"shll.ph", "d,t,4", 0x7c000213, 0xfe0007ff, WR_d|RD_t, 0, D32 }, -{"shll.pw", "d,t,6", 0x7c000417, 0xfc0007ff, WR_d|RD_t, 0, D64 }, -{"shll.qb", "d,t,3", 0x7c000013, 0xff0007ff, WR_d|RD_t, 0, D32 }, -{"shll.qh", "d,t,4", 0x7c000217, 0xfe0007ff, WR_d|RD_t, 0, D64 }, -{"shll_s.ph", "d,t,4", 0x7c000313, 0xfe0007ff, WR_d|RD_t, 0, D32 }, -{"shll_s.pw", "d,t,6", 0x7c000517, 0xfc0007ff, WR_d|RD_t, 0, D64 }, -{"shll_s.qh", "d,t,4", 0x7c000317, 0xfe0007ff, WR_d|RD_t, 0, D64 }, -{"shll_s.w", "d,t,6", 0x7c000513, 0xfc0007ff, WR_d|RD_t, 0, D32 }, -{"shllv.ob", "d,t,s", 0x7c000097, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shllv.ph", "d,t,s", 0x7c000293, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"shllv.pw", "d,t,s", 0x7c000497, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shllv.qb", "d,t,s", 0x7c000093, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"shllv.qh", "d,t,s", 0x7c000297, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shllv_s.ph", "d,t,s", 0x7c000393, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"shllv_s.pw", "d,t,s", 0x7c000597, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shllv_s.qh", "d,t,s", 0x7c000397, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shllv_s.w", "d,t,s", 0x7c000593, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"shra.ph", "d,t,4", 0x7c000253, 0xfe0007ff, WR_d|RD_t, 0, D32 }, -{"shra.pw", "d,t,6", 0x7c000457, 0xfc0007ff, WR_d|RD_t, 0, D64 }, -{"shra.qh", "d,t,4", 0x7c000257, 0xfe0007ff, WR_d|RD_t, 0, D64 }, -{"shra_r.ph", "d,t,4", 0x7c000353, 0xfe0007ff, WR_d|RD_t, 0, D32 }, -{"shra_r.pw", "d,t,6", 0x7c000557, 0xfc0007ff, WR_d|RD_t, 0, D64 }, -{"shra_r.qh", "d,t,4", 0x7c000357, 0xfe0007ff, WR_d|RD_t, 0, D64 }, -{"shra_r.w", "d,t,6", 0x7c000553, 0xfc0007ff, WR_d|RD_t, 0, D32 }, -{"shrav.ph", "d,t,s", 0x7c0002d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"shrav.pw", "d,t,s", 0x7c0004d7, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shrav.qh", "d,t,s", 0x7c0002d7, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shrav_r.ph", "d,t,s", 0x7c0003d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"shrav_r.pw", "d,t,s", 0x7c0005d7, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shrav_r.qh", "d,t,s", 0x7c0003d7, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shrav_r.w", "d,t,s", 0x7c0005d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"shrl.ob", "d,t,3", 0x7c000057, 0xff0007ff, WR_d|RD_t, 0, D64 }, -{"shrl.qb", "d,t,3", 0x7c000053, 0xff0007ff, WR_d|RD_t, 0, D32 }, -{"shrlv.ob", "d,t,s", 0x7c0000d7, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"shrlv.qb", "d,t,s", 0x7c0000d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"subq.ph", "d,s,t", 0x7c0002d0, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"subq.pw", "d,s,t", 0x7c0004d4, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"subq.qh", "d,s,t", 0x7c0002d4, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"subq_s.ph", "d,s,t", 0x7c0003d0, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"subq_s.pw", "d,s,t", 0x7c0005d4, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"subq_s.qh", "d,s,t", 0x7c0003d4, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"subq_s.w", "d,s,t", 0x7c0005d0, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"subu.ob", "d,s,t", 0x7c000054, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"subu.qb", "d,s,t", 0x7c000050, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"subu_s.ob", "d,s,t", 0x7c000154, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D64 }, -{"subu_s.qb", "d,s,t", 0x7c000150, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, -{"wrdsp", "s", 0x7c1ffcf8, 0xfc1fffff, RD_s|DSP_VOLA, 0, D32 }, -{"wrdsp", "s,8", 0x7c0004f8, 0xfc1e07ff, RD_s|DSP_VOLA, 0, D32 }, -/* MIPS DSP ASE Rev2 */ -{"absq_s.qb", "d,t", 0x7c000052, 0xffe007ff, WR_d|RD_t, 0, D33 }, -{"addu.ph", "d,s,t", 0x7c000210, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"addu_s.ph", "d,s,t", 0x7c000310, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"adduh.qb", "d,s,t", 0x7c000018, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"adduh_r.qb", "d,s,t", 0x7c000098, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"append", "t,s,h", 0x7c000031, 0xfc0007ff, WR_t|RD_t|RD_s, 0, D33 }, -{"balign", "t,s,I", 0, (int) M_BALIGN, INSN_MACRO, 0, D33 }, -{"balign", "t,s,2", 0x7c000431, 0xfc00e7ff, WR_t|RD_t|RD_s, 0, D33 }, -{"cmpgdu.eq.qb", "d,s,t", 0x7c000611, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"cmpgdu.lt.qb", "d,s,t", 0x7c000651, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"cmpgdu.le.qb", "d,s,t", 0x7c000691, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"dpa.w.ph", "7,s,t", 0x7c000030, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"dps.w.ph", "7,s,t", 0x7c000070, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"mul.ph", "d,s,t", 0x7c000318, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D33 }, -{"mul_s.ph", "d,s,t", 0x7c000398, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D33 }, -{"mulq_rs.w", "d,s,t", 0x7c0005d8, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D33 }, -{"mulq_s.ph", "d,s,t", 0x7c000790, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D33 }, -{"mulq_s.w", "d,s,t", 0x7c000598, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HILO, 0, D33 }, -{"mulsa.w.ph", "7,s,t", 0x7c0000b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"precr.qb.ph", "d,s,t", 0x7c000351, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"precr_sra.ph.w", "t,s,h", 0x7c000791, 0xfc0007ff, WR_t|RD_t|RD_s, 0, D33 }, -{"precr_sra_r.ph.w", "t,s,h", 0x7c0007d1, 0xfc0007ff, WR_t|RD_t|RD_s, 0, D33 }, -{"prepend", "t,s,h", 0x7c000071, 0xfc0007ff, WR_t|RD_t|RD_s, 0, D33 }, -{"shra.qb", "d,t,3", 0x7c000113, 0xff0007ff, WR_d|RD_t, 0, D33 }, -{"shra_r.qb", "d,t,3", 0x7c000153, 0xff0007ff, WR_d|RD_t, 0, D33 }, -{"shrav.qb", "d,t,s", 0x7c000193, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"shrav_r.qb", "d,t,s", 0x7c0001d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"shrl.ph", "d,t,4", 0x7c000653, 0xfe0007ff, WR_d|RD_t, 0, D33 }, -{"shrlv.ph", "d,t,s", 0x7c0006d3, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subu.ph", "d,s,t", 0x7c000250, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subu_s.ph", "d,s,t", 0x7c000350, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subuh.qb", "d,s,t", 0x7c000058, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subuh_r.qb", "d,s,t", 0x7c0000d8, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"addqh.ph", "d,s,t", 0x7c000218, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"addqh_r.ph", "d,s,t", 0x7c000298, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"addqh.w", "d,s,t", 0x7c000418, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"addqh_r.w", "d,s,t", 0x7c000498, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subqh.ph", "d,s,t", 0x7c000258, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subqh_r.ph", "d,s,t", 0x7c0002d8, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subqh.w", "d,s,t", 0x7c000458, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"subqh_r.w", "d,s,t", 0x7c0004d8, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D33 }, -{"dpax.w.ph", "7,s,t", 0x7c000230, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"dpsx.w.ph", "7,s,t", 0x7c000270, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"dpaqx_s.w.ph", "7,s,t", 0x7c000630, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"dpaqx_sa.w.ph", "7,s,t", 0x7c0006b0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"dpsqx_s.w.ph", "7,s,t", 0x7c000670, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -{"dpsqx_sa.w.ph", "7,s,t", 0x7c0006f0, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, -/* Move bc0* after mftr and mttr to avoid opcode collision. */ -{"bc0f", "p", 0x41000000, 0xffff0000, CBD|RD_CC, 0, I1 }, -{"bc0fl", "p", 0x41020000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, -{"bc0t", "p", 0x41010000, 0xffff0000, CBD|RD_CC, 0, I1 }, -{"bc0tl", "p", 0x41030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, -/* ST Microelectronics Loongson-2E and -2F. */ -{"faddu", "D,V,T", 0x45800000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"for", "D,V,T", 0x45a00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fadd", "D,V,T", 0x45c00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fdadd", "D,V,T", 0x45e00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fsubu", "D,V,T", 0x45800001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fsub", "D,V,T", 0x45c00001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fdsub", "D,V,T", 0x45e00001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fsll", "D,V,T", 0x45800002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fdsll", "D,V,T", 0x45a00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fxor", "D,V,T", 0x47800002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fnor", "D,V,T", 0x47a00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fand", "D,V,T", 0x47c00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fsrl", "D,V,T", 0x45800003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fdsrl", "D,V,T", 0x45a00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fsra", "D,V,T", 0x45c00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fdsra", "D,V,T", 0x45e00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"fseq", "S,T", 0x46800032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"fseq1", "S,T", 0x46a00032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"fsltu", "S,T", 0x4680003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"fslt", "S,T", 0x46a0003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"fsleu", "S,T", 0x4680003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"fsle", "S,T", 0x46a0003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -/* loongson 2f */ -{"faddu", "D,V,T", 0x45800000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"for", "D,V,T", 0x45a00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fadd", "D,V,T", 0x45c00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fdadd", "D,V,T", 0x45e00000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fsubu", "D,V,T", 0x45800001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fsub", "D,V,T", 0x45c00001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fdsub", "D,V,T", 0x45e00001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fsll", "D,V,T", 0x45800002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fdsll", "D,V,T", 0x45a00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fxor", "D,V,T", 0x47800002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fnor", "D,V,T", 0x47a00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fand", "D,V,T", 0x47c00002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fsrl", "D,V,T", 0x45800003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fdsrl", "D,V,T", 0x45a00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fsra", "D,V,T", 0x45c00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fdsra", "D,V,T", 0x45e00003, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2F }, -{"fseq", "S,T", 0x46800032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"fseq1", "S,T", 0x46a00032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"fsltu", "S,T", 0x4680003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"fslt", "S,T", 0x46a0003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"fsleu", "S,T", 0x4680003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -{"fsle", "S,T", 0x46a0003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -/* loongson2 paired single */ -{"add.gps", "D,V,T", 0x45600000, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"sub.gps", "D,V,T", 0x45600001, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"mul.gps", "D,V,T", 0x45600002, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, IL2E }, -{"abs.gps", "D,V", 0x45600005, 0xffff003f, WR_D|RD_S|FP_D, 0, IL2E }, -{"mov.gps", "D,S", 0x45600006, 0xffff003f, WR_D|RD_S|FP_D, 0, IL2E }, -{"neg.gps", "D,V", 0x45600007, 0xffff003f, WR_D|RD_S|FP_D, 0, IL2E }, -{"c.f.gps", "S,T", 0x45600030, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.un.gps", "S,T", 0x45600031, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.eq.gps", "S,T", 0x45600032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ueq.gps", "S,T", 0x45600033, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.olt.gps", "S,T", 0x45600034, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ult.gps", "S,T", 0x45600035, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ole.gps", "S,T", 0x45600036, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ule.gps", "S,T", 0x45600037, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.sf.gps", "S,T", 0x45600038, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ngle.gps", "S,T", 0x45600039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ngle.gps", "S,T", 0x45600039, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.seq.gps", "S,T", 0x4560003a, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ngl.gps", "S,T", 0x4560003b, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.lt.gps", "S,T", 0x4560003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.nge.gps", "S,T", 0x4560003d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.le.gps", "S,T", 0x4560003e, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"c.ngt.gps", "S,T", 0x4560003f, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, - -{"mult.g", "d,s,t", 0x7c000018, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"mult.g", "d,s,t", 0x70000010, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"multu.g", "d,s,t", 0x7c000019, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"multu.g", "d,s,t", 0x70000012, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"dmult.g", "d,s,t", 0x7c00001c, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"dmult.g", "d,s,t", 0x70000011, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"dmultu.g", "d,s,t", 0x7c00001d, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"dmultu.g", "d,s,t", 0x70000013, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"div.g", "d,s,t", 0x7c00001a, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"div.g", "d,s,t", 0x70000014, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"divu.g", "d,s,t", 0x7c00001b, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"divu.g", "d,s,t", 0x70000016, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"ddiv.g", "d,s,t", 0x7c00001e, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"ddiv.g", "d,s,t", 0x70000015, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"ddivu.g", "d,s,t", 0x7c00001f, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"ddivu.g", "d,s,t", 0x70000017, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"mod.g", "d,s,t", 0x7c000022, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"mod.g", "d,s,t", 0x7000001c, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"modu.g", "d,s,t", 0x7c000023, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"modu.g", "d,s,t", 0x7000001e, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"dmod.g", "d,s,t", 0x7c000026, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"dmod.g", "d,s,t", 0x7000001d, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"dmodu.g", "d,s,t", 0x7c000027, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2E }, -{"dmodu.g", "d,s,t", 0x7000001f, 0xfc0007ff, RD_s|RD_t|WR_d, 0, IL2F }, -{"packsshb", "D,S,T", 0x47400002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"packsshb", "D,S,T", 0x4b400002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"packsswh", "D,S,T", 0x47200002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"packsswh", "D,S,T", 0x4b200002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"packushb", "D,S,T", 0x47600002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"packushb", "D,S,T", 0x4b600002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddb", "D,S,T", 0x47c00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddb", "D,S,T", 0x4bc00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddh", "D,S,T", 0x47400000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddh", "D,S,T", 0x4b400000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddw", "D,S,T", 0x47600000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddw", "D,S,T", 0x4b600000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddd", "D,S,T", 0x47e00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddd", "D,S,T", 0x4be00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddsb", "D,S,T", 0x47800000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddsb", "D,S,T", 0x4b800000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddsh", "D,S,T", 0x47000000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddsh", "D,S,T", 0x4b000000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddusb", "D,S,T", 0x47a00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddusb", "D,S,T", 0x4ba00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"paddush", "D,S,T", 0x47200000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"paddush", "D,S,T", 0x4b200000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pandn", "D,S,T", 0x47e00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pandn", "D,S,T", 0x4be00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pavgb", "D,S,T", 0x46600000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pavgb", "D,S,T", 0x4b200008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pavgh", "D,S,T", 0x46400000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pavgh", "D,S,T", 0x4b000008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pcmpeqb", "D,S,T", 0x46c00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pcmpeqb", "D,S,T", 0x4b800009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pcmpeqh", "D,S,T", 0x46800001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pcmpeqh", "D,S,T", 0x4b400009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pcmpeqw", "D,S,T", 0x46400001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pcmpeqw", "D,S,T", 0x4b000009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pcmpgtb", "D,S,T", 0x46e00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pcmpgtb", "D,S,T", 0x4ba00009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pcmpgth", "D,S,T", 0x46a00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pcmpgth", "D,S,T", 0x4b600009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pcmpgtw", "D,S,T", 0x46600001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pcmpgtw", "D,S,T", 0x4b200009, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pextrh", "D,S,T", 0x45c00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pextrh", "D,S,T", 0x4b40000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pinsrh_0", "D,S,T", 0x47800003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pinsrh_0", "D,S,T", 0x4b800003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pinsrh_1", "D,S,T", 0x47a00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pinsrh_1", "D,S,T", 0x4ba00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pinsrh_2", "D,S,T", 0x47c00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pinsrh_2", "D,S,T", 0x4bc00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pinsrh_3", "D,S,T", 0x47e00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pinsrh_3", "D,S,T", 0x4be00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pmaddhw", "D,S,T", 0x45e00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pmaddhw", "D,S,T", 0x4b60000e, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pmaxsh", "D,S,T", 0x46800000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pmaxsh", "D,S,T", 0x4b400008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pmaxub", "D,S,T", 0x46c00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pmaxub", "D,S,T", 0x4b800008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pminsh", "D,S,T", 0x46a00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pminsh", "D,S,T", 0x4b600008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pminub", "D,S,T", 0x46e00000, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pminub", "D,S,T", 0x4ba00008, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pmovmskb", "D,S", 0x46a00005, 0xffff003f, RD_S|WR_D|FP_D, 0, IL2E }, -{"pmovmskb", "D,S", 0x4ba0000f, 0xffff003f, RD_S|WR_D|FP_D, 0, IL2F }, -{"pmulhuh", "D,S,T", 0x46e00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pmulhuh", "D,S,T", 0x4ba0000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pmulhh", "D,S,T", 0x46a00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pmulhh", "D,S,T", 0x4b60000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pmullh", "D,S,T", 0x46800002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pmullh", "D,S,T", 0x4b40000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pmuluw", "D,S,T", 0x46c00002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pmuluw", "D,S,T", 0x4b80000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"pasubub", "D,S,T", 0x45a00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pasubub", "D,S,T", 0x4b20000d, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"biadd", "D,S", 0x46800005, 0xffff003f, RD_S|WR_D|FP_D, 0, IL2E }, -{"biadd", "D,S", 0x4b80000f, 0xffff003f, RD_S|WR_D|FP_D, 0, IL2F }, -{"pshufh", "D,S,T", 0x47000002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"pshufh", "D,S,T", 0x4b000002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psllh", "D,S,T", 0x46600002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psllh", "D,S,T", 0x4b20000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psllw", "D,S,T", 0x46400002, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psllw", "D,S,T", 0x4b00000a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psrah", "D,S,T", 0x46a00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psrah", "D,S,T", 0x4b60000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psraw", "D,S,T", 0x46800003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psraw", "D,S,T", 0x4b40000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psrlh", "D,S,T", 0x46600003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psrlh", "D,S,T", 0x4b20000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psrlw", "D,S,T", 0x46400003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psrlw", "D,S,T", 0x4b00000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubb", "D,S,T", 0x47c00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubb", "D,S,T", 0x4bc00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubh", "D,S,T", 0x47400001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubh", "D,S,T", 0x4b400001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubw", "D,S,T", 0x47600001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubw", "D,S,T", 0x4b600001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubd", "D,S,T", 0x47e00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubd", "D,S,T", 0x4be00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubsb", "D,S,T", 0x47800001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubsb", "D,S,T", 0x4b800001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubsh", "D,S,T", 0x47000001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubsh", "D,S,T", 0x4b000001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubusb", "D,S,T", 0x47a00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubusb", "D,S,T", 0x4ba00001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"psubush", "D,S,T", 0x47200001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"psubush", "D,S,T", 0x4b200001, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"punpckhbh", "D,S,T", 0x47600003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"punpckhbh", "D,S,T", 0x4b600003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"punpckhhw", "D,S,T", 0x47200003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"punpckhhw", "D,S,T", 0x4b200003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"punpckhwd", "D,S,T", 0x46e00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"punpckhwd", "D,S,T", 0x4ba0000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"punpcklbh", "D,S,T", 0x47400003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"punpcklbh", "D,S,T", 0x4b400003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"punpcklhw", "D,S,T", 0x47000003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"punpcklhw", "D,S,T", 0x4b000003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"punpcklwd", "D,S,T", 0x46c00003, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, -{"punpcklwd", "D,S,T", 0x4b80000b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, -{"sequ", "S,T", 0x46800032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E }, -{"sequ", "S,T", 0x4b80000c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F }, -/* No hazard protection on coprocessor instructions--they shouldn't - change the state of the processor and if they do it's up to the - user to put in nops as necessary. These are at the end so that the - disassembler recognizes more specific versions first. */ -{"c0", "C", 0x42000000, 0xfe000000, 0, 0, I1 }, -{"c1", "C", 0x46000000, 0xfe000000, 0, 0, I1 }, -{"c2", "C", 0x4a000000, 0xfe000000, 0, 0, I1 }, -{"c3", "C", 0x4e000000, 0xfe000000, 0, 0, I1 }, -{"cop0", "C", 0, (int) M_COP0, INSN_MACRO, 0, I1 }, -{"cop1", "C", 0, (int) M_COP1, INSN_MACRO, 0, I1 }, -{"cop2", "C", 0, (int) M_COP2, INSN_MACRO, 0, I1 }, -{"cop3", "C", 0, (int) M_COP3, INSN_MACRO, 0, I1 } -}; - -#define MIPS_NUM_OPCODES \ - ((sizeof mips_builtin_opcodes) / (sizeof (mips_builtin_opcodes[0]))) -const int bfd_mips_num_builtin_opcodes = MIPS_NUM_OPCODES; - -/* const removed from the following to allow for dynamic extensions to the - * built-in instruction set. */ -struct mips_opcode *mips_opcodes = - (struct mips_opcode *) mips_builtin_opcodes; -int bfd_mips_num_opcodes = MIPS_NUM_OPCODES; -#undef MIPS_NUM_OPCODES diff --git a/librz/arch/isa_gnu/mips/mips16-opc.c b/librz/arch/isa_gnu/mips/mips16-opc.c deleted file mode 100644 index a1eaeb3b325..00000000000 --- a/librz/arch/isa_gnu/mips/mips16-opc.c +++ /dev/null @@ -1,244 +0,0 @@ -/* mips16-opc.c. Mips16 opcode table. - Copyright 1996, 1997, 1998, 2000, 2005, 2007 Free Software Foundation, Inc. - Contributed by Ian Lance Taylor, Cygnus Support - - This file is part of the GNU opcodes library. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - It is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with this file; see the file COPYING. If not, write to the - Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, - MA 02110-1301, USA. */ - -#include -#include -#include - -/* This is the opcodes table for the mips16 processor. The format of - this table is intentionally identical to the one in mips-opc.c. - However, the special letters that appear in the argument string are - different, and the table uses some different flags. */ - -/* Use some short hand macros to keep down the length of the lines in - the opcodes table. */ - -#define UBD INSN_UNCOND_BRANCH_DELAY -#define BR MIPS16_INSN_BRANCH - -#define WR_x MIPS16_INSN_WRITE_X -#define WR_y MIPS16_INSN_WRITE_Y -#define WR_z MIPS16_INSN_WRITE_Z -#define WR_T MIPS16_INSN_WRITE_T -#define WR_SP MIPS16_INSN_WRITE_SP -#define WR_31 MIPS16_INSN_WRITE_31 -#define WR_Y MIPS16_INSN_WRITE_GPR_Y - -#define RD_x MIPS16_INSN_READ_X -#define RD_y MIPS16_INSN_READ_Y -#define RD_Z MIPS16_INSN_READ_Z -#define RD_T MIPS16_INSN_READ_T -#define RD_SP MIPS16_INSN_READ_SP -#define RD_31 MIPS16_INSN_READ_31 -#define RD_PC MIPS16_INSN_READ_PC -#define RD_X MIPS16_INSN_READ_GPR_X - -#define WR_HI INSN_WRITE_HI -#define WR_LO INSN_WRITE_LO -#define RD_HI INSN_READ_HI -#define RD_LO INSN_READ_LO - -#define TRAP INSN_TRAP - -#define I1 INSN_ISA1 -#define I3 INSN_ISA3 -#define I32 INSN_ISA32 -#define I64 INSN_ISA64 -#define T3 INSN_3900 - -const struct mips_opcode mips16_opcodes[] = -{ -/* name, args, match, mask, pinfo, pinfo2, membership */ -{"nop", "", 0x6500, 0xffff, RD_Z, 0, I1 }, /* move $0,$Z */ -{"la", "x,A", 0x0800, 0xf800, WR_x|RD_PC, 0, I1 }, -{"abs", "x,w", 0, (int) M_ABS, INSN_MACRO, 0, I1 }, -{"addiu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0, I1 }, -{"addiu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0, I1 }, -{"addiu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 }, -{"addiu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 }, -{"addiu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0, I1 }, -{"addiu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0, I1 }, -{"addu", "z,v,y", 0xe001, 0xf803, WR_z|RD_x|RD_y, 0, I1 }, -{"addu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0, I1 }, -{"addu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0, I1 }, -{"addu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 }, -{"addu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 }, -{"addu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0, I1 }, -{"addu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0, I1 }, -{"and", "x,y", 0xe80c, 0xf81f, WR_x|RD_x|RD_y, 0, I1 }, -{"b", "q", 0x1000, 0xf800, BR, 0, I1 }, -{"beq", "x,y,p", 0, (int) M_BEQ, INSN_MACRO, 0, I1 }, -{"beq", "x,U,p", 0, (int) M_BEQ_I, INSN_MACRO, 0, I1 }, -{"beqz", "x,p", 0x2000, 0xf800, BR|RD_x, 0, I1 }, -{"bge", "x,y,p", 0, (int) M_BGE, INSN_MACRO, 0, I1 }, -{"bge", "x,8,p", 0, (int) M_BGE_I, INSN_MACRO, 0, I1 }, -{"bgeu", "x,y,p", 0, (int) M_BGEU, INSN_MACRO, 0, I1 }, -{"bgeu", "x,8,p", 0, (int) M_BGEU_I, INSN_MACRO, 0, I1 }, -{"bgt", "x,y,p", 0, (int) M_BGT, INSN_MACRO, 0, I1 }, -{"bgt", "x,8,p", 0, (int) M_BGT_I, INSN_MACRO, 0, I1 }, -{"bgtu", "x,y,p", 0, (int) M_BGTU, INSN_MACRO, 0, I1 }, -{"bgtu", "x,8,p", 0, (int) M_BGTU_I, INSN_MACRO, 0, I1 }, -{"ble", "x,y,p", 0, (int) M_BLE, INSN_MACRO, 0, I1 }, -{"ble", "x,8,p", 0, (int) M_BLE_I, INSN_MACRO, 0, I1 }, -{"bleu", "x,y,p", 0, (int) M_BLEU, INSN_MACRO, 0, I1 }, -{"bleu", "x,8,p", 0, (int) M_BLEU_I, INSN_MACRO, 0, I1 }, -{"blt", "x,y,p", 0, (int) M_BLT, INSN_MACRO, 0, I1 }, -{"blt", "x,8,p", 0, (int) M_BLT_I, INSN_MACRO, 0, I1 }, -{"bltu", "x,y,p", 0, (int) M_BLTU, INSN_MACRO, 0, I1 }, -{"bltu", "x,8,p", 0, (int) M_BLTU_I, INSN_MACRO, 0, I1 }, -{"bne", "x,y,p", 0, (int) M_BNE, INSN_MACRO, 0, I1 }, -{"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I1 }, -{"bnez", "x,p", 0x2800, 0xf800, BR|RD_x, 0, I1 }, -{"break", "6", 0xe805, 0xf81f, TRAP, 0, I1 }, -{"bteqz", "p", 0x6000, 0xff00, BR|RD_T, 0, I1 }, -{"btnez", "p", 0x6100, 0xff00, BR|RD_T, 0, I1 }, -{"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, I1 }, -{"cmp", "x,y", 0xe80a, 0xf81f, WR_T|RD_x|RD_y, 0, I1 }, -{"cmp", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, I1 }, -{"dla", "y,E", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 }, -{"daddiu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, 0, I3 }, -{"daddiu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, 0, I3 }, -{"daddiu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, -{"daddiu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, -{"daddiu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 }, -{"daddiu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, 0, I3 }, -{"daddu", "z,v,y", 0xe000, 0xf803, WR_z|RD_x|RD_y, 0, I3 }, -{"daddu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, 0, I3 }, -{"daddu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, 0, I3 }, -{"daddu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, -{"daddu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 }, -{"daddu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 }, -{"daddu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, 0, I3 }, -{"ddiv", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, -{"ddiv", "z,v,y", 0, (int) M_DDIV_3, INSN_MACRO, 0, I1 }, -{"ddivu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, -{"ddivu", "z,v,y", 0, (int) M_DDIVU_3, INSN_MACRO, 0, I1 }, -{"div", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, -{"div", "z,v,y", 0, (int) M_DIV_3, INSN_MACRO, 0, I1 }, -{"divu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, -{"divu", "z,v,y", 0, (int) M_DIVU_3, INSN_MACRO, 0, I1 }, -{"dmul", "z,v,y", 0, (int) M_DMUL, INSN_MACRO, 0, I3 }, -{"dmult", "x,y", 0xe81c, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, -{"dmultu", "x,y", 0xe81d, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, -{"drem", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, -{"drem", "z,v,y", 0, (int) M_DREM_3, INSN_MACRO, 0, I1 }, -{"dremu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 }, -{"dremu", "z,v,y", 0, (int) M_DREMU_3, INSN_MACRO, 0, I1 }, -{"dsllv", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, -{"dsll", "x,w,[", 0x3001, 0xf803, WR_x|RD_y, 0, I3 }, -{"dsll", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, -{"dsrav", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, -{"dsra", "y,]", 0xe813, 0xf81f, WR_y|RD_y, 0, I3 }, -{"dsra", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, -{"dsrlv", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, -{"dsrl", "y,]", 0xe808, 0xf81f, WR_y|RD_y, 0, I3 }, -{"dsrl", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, 0, I3 }, -{"dsubu", "z,v,y", 0xe002, 0xf803, WR_z|RD_x|RD_y, 0, I3 }, -{"dsubu", "y,x,4", 0, (int) M_DSUBU_I, INSN_MACRO, 0, I1 }, -{"dsubu", "y,j", 0, (int) M_DSUBU_I_2, INSN_MACRO, 0, I1 }, -{"exit", "L", 0xed09, 0xff1f, TRAP, 0, I1 }, -{"exit", "L", 0xee09, 0xff1f, TRAP, 0, I1 }, -{"exit", "L", 0xef09, 0xff1f, TRAP, 0, I1 }, -{"entry", "l", 0xe809, 0xf81f, TRAP, 0, I1 }, -{"extend", "e", 0xf000, 0xf800, 0, 0, I1 }, -{"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 }, -{"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 }, -{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 }, -{"jal", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 }, -{"jal", "a", 0x1800, 0xfc00, UBD|WR_31, 0, I1 }, -{"jalx", "a", 0x1c00, 0xfc00, UBD|WR_31, 0, I1 }, -{"jr", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, I1 }, -{"jr", "R", 0xe820, 0xffff, UBD|RD_31, 0, I1 }, -{"j", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, I1 }, -{"j", "R", 0xe820, 0xffff, UBD|RD_31, 0, I1 }, -{"lb", "y,5(x)", 0x8000, 0xf800, WR_y|RD_x, 0, I1 }, -{"lbu", "y,5(x)", 0xa000, 0xf800, WR_y|RD_x, 0, I1 }, -{"ld", "y,D(x)", 0x3800, 0xf800, WR_y|RD_x, 0, I3 }, -{"ld", "y,B", 0xfc00, 0xff00, WR_y|RD_PC, 0, I3 }, -{"ld", "y,D(P)", 0xfc00, 0xff00, WR_y|RD_PC, 0, I3 }, -{"ld", "y,D(S)", 0xf800, 0xff00, WR_y|RD_SP, 0, I3 }, -{"lh", "y,H(x)", 0x8800, 0xf800, WR_y|RD_x, 0, I1 }, -{"lhu", "y,H(x)", 0xa800, 0xf800, WR_y|RD_x, 0, I1 }, -{"li", "x,U", 0x6800, 0xf800, WR_x, 0, I1 }, -{"lw", "y,W(x)", 0x9800, 0xf800, WR_y|RD_x, 0, I1 }, -{"lw", "x,A", 0xb000, 0xf800, WR_x|RD_PC, 0, I1 }, -{"lw", "x,V(P)", 0xb000, 0xf800, WR_x|RD_PC, 0, I1 }, -{"lw", "x,V(S)", 0x9000, 0xf800, WR_x|RD_SP, 0, I1 }, -{"lwu", "y,W(x)", 0xb800, 0xf800, WR_y|RD_x, 0, I3 }, -{"mfhi", "x", 0xe810, 0xf8ff, WR_x|RD_HI, 0, I1 }, -{"mflo", "x", 0xe812, 0xf8ff, WR_x|RD_LO, 0, I1 }, -{"move", "y,X", 0x6700, 0xff00, WR_y|RD_X, 0, I1 }, -{"move", "Y,Z", 0x6500, 0xff00, WR_Y|RD_Z, 0, I1 }, -{"mul", "z,v,y", 0, (int) M_MUL, INSN_MACRO, 0, I1 }, -{"mult", "x,y", 0xe818, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, -{"multu", "x,y", 0xe819, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, -{"neg", "x,w", 0xe80b, 0xf81f, WR_x|RD_y, 0, I1 }, -{"not", "x,w", 0xe80f, 0xf81f, WR_x|RD_y, 0, I1 }, -{"or", "x,y", 0xe80d, 0xf81f, WR_x|RD_x|RD_y, 0, I1 }, -{"rem", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, -{"rem", "z,v,y", 0, (int) M_REM_3, INSN_MACRO, 0, I1 }, -{"remu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, -{"remu", "z,v,y", 0, (int) M_REMU_3, INSN_MACRO, 0, I1 }, -{"sb", "y,5(x)", 0xc000, 0xf800, RD_y|RD_x, 0, I1 }, -{"sd", "y,D(x)", 0x7800, 0xf800, RD_y|RD_x, 0, I3 }, -{"sd", "y,D(S)", 0xf900, 0xff00, RD_y|RD_PC, 0, I3 }, -{"sd", "R,C(S)", 0xfa00, 0xff00, RD_31|RD_PC, 0, I1 }, -{"sh", "y,H(x)", 0xc800, 0xf800, RD_y|RD_x, 0, I1 }, -{"sllv", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0, I1 }, -{"sll", "x,w,<", 0x3000, 0xf803, WR_x|RD_y, 0, I1 }, -{"sll", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0, I1 }, -{"slti", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0, I1 }, -{"slt", "x,y", 0xe802, 0xf81f, WR_T|RD_x|RD_y, 0, I1 }, -{"slt", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0, I1 }, -{"sltiu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0, I1 }, -{"sltu", "x,y", 0xe803, 0xf81f, WR_T|RD_x|RD_y, 0, I1 }, -{"sltu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0, I1 }, -{"srav", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0, I1 }, -{"sra", "x,w,<", 0x3003, 0xf803, WR_x|RD_y, 0, I1 }, -{"sra", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0, I1 }, -{"srlv", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0, I1 }, -{"srl", "x,w,<", 0x3002, 0xf803, WR_x|RD_y, 0, I1 }, -{"srl", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0, I1 }, -{"subu", "z,v,y", 0xe003, 0xf803, WR_z|RD_x|RD_y, 0, I1 }, -{"subu", "y,x,4", 0, (int) M_SUBU_I, INSN_MACRO, 0, I1 }, -{"subu", "x,k", 0, (int) M_SUBU_I_2, INSN_MACRO,0, I1 }, -{"sw", "y,W(x)", 0xd800, 0xf800, RD_y|RD_x, 0, I1 }, -{"sw", "x,V(S)", 0xd000, 0xf800, RD_x|RD_SP, 0, I1 }, -{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP, 0, I1 }, -{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y, 0, I1 }, - /* MIPS16e additions */ -{"jalrc", "x", 0xe8c0, 0xf8ff, WR_31|RD_x|TRAP, 0, I32 }, -{"jalrc", "R,x", 0xe8c0, 0xf8ff, WR_31|RD_x|TRAP, 0, I32 }, -{"jrc", "x", 0xe880, 0xf8ff, RD_x|TRAP, 0, I32 }, -{"jrc", "R", 0xe8a0, 0xffff, RD_31|TRAP, 0, I32 }, -{"restore", "M", 0x6400, 0xff80, WR_31|RD_SP|WR_SP|TRAP, 0, I32 }, -{"save", "m", 0x6480, 0xff80, RD_31|RD_SP|WR_SP|TRAP, 0, I32 }, -{"sdbbp", "6", 0xe801, 0xf81f, TRAP, 0, I32 }, -{"seb", "x", 0xe891, 0xf8ff, WR_x|RD_x, 0, I32 }, -{"seh", "x", 0xe8b1, 0xf8ff, WR_x|RD_x, 0, I32 }, -{"sew", "x", 0xe8d1, 0xf8ff, WR_x|RD_x, 0, I64 }, -{"zeb", "x", 0xe811, 0xf8ff, WR_x|RD_x, 0, I32 }, -{"zeh", "x", 0xe831, 0xf8ff, WR_x|RD_x, 0, I32 }, -{"zew", "x", 0xe851, 0xf8ff, WR_x|RD_x, 0, I64 }, -}; - -const int bfd_mips16_num_opcodes = - ((sizeof mips16_opcodes) / (sizeof (mips16_opcodes[0]))); diff --git a/librz/arch/meson.build b/librz/arch/meson.build index d03a269324c..5837aa4556e 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -31,7 +31,7 @@ arch_plugins_list = [ 'malbolge', 'mcore', 'mcs96', - 'mips_cs', + 'mips', 'msp430', 'null', 'or1k', @@ -88,7 +88,7 @@ arch_plugin_sources = [ 'p/arch_malbolge.c', 'p/arch_mcore.c', 'p/arch_mcs96.c', - 'p/arch_mips_cs.c', + 'p/arch_mips.c', 'p/arch_msp430.c', 'p/arch_null.c', 'p/arch_or1k.c', @@ -218,6 +218,7 @@ arch_isa_sources = [ 'isa/luac/v54/opcode_54.c', 'isa/mcore/mcore.c', 'isa/mips/mips_assembler.c', + 'isa/mips/mips_esil.c', 'isa/msp430/msp430_disas.c', 'isa/msp430/msp430_il.c', 'isa/or1k/or1k_disas.c', @@ -349,7 +350,6 @@ if get_option('use_gpl') 'cris_gnu', 'hppa_gnu', 'lanai_gnu', - 'mips_gnu', 'riscv_gnu', 'sparc_gnu', 'vax_gnu', @@ -362,7 +362,6 @@ if get_option('use_gpl') 'p_gnu/arch_cris.c', 'p_gnu/arch_hppa.c', 'p_gnu/arch_lanai.c', - 'p_gnu/arch_mips.c', 'p_gnu/arch_riscv.c', 'p_gnu/arch_sparc.c', 'p_gnu/arch_vax.c', @@ -380,9 +379,6 @@ if get_option('use_gpl') 'isa_gnu/hppa/hppa-dis.c', 'isa_gnu/lanai/lanai-dis.c', 'isa_gnu/lanai/lanai-opc.c', - 'isa_gnu/mips/mips-dis.c', - 'isa_gnu/mips/mips-opc.c', - 'isa_gnu/mips/mips16-opc.c', # 'isa_gnu/riscv/riscv-opc.c', # 'isa_gnu/riscv/riscv.c', 'isa_gnu/sparc/sparc-dis.c', diff --git a/librz/arch/p/analysis/analysis_luac.c b/librz/arch/p/analysis/analysis_luac.c index aa78250a29d..e8d8ca75789 100644 --- a/librz/arch/p/analysis/analysis_luac.c +++ b/librz/arch/p/analysis/analysis_luac.c @@ -11,9 +11,9 @@ int rz_lua_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const RZ_LOG_ERROR("Cannot get lua version\n"); return 0; } - if (strcmp(analysis->cpu, "5.4") == 0) { + if (!strcmp(analysis->cpu, "5.4")) { return lua54_anal_op(analysis, op, addr, data, len); - } else if (strcmp(analysis->cpu, "5.3") == 0) { + } else if (!strcmp(analysis->cpu, "5.3")) { return lua53_anal_op(analysis, op, addr, data, len); } else { RZ_LOG_ERROR("Cannot find a suitable lua version to handle lua analysis\n"); diff --git a/librz/arch/p/analysis/analysis_mips_cs.c b/librz/arch/p/analysis/analysis_mips.c similarity index 54% rename from librz/arch/p/analysis/analysis_mips_cs.c rename to librz/arch/p/analysis/analysis_mips.c index ed64921ff8d..75c781d829d 100644 --- a/librz/arch/p/analysis/analysis_mips_cs.c +++ b/librz/arch/p/analysis/analysis_mips.c @@ -3,8 +3,7 @@ #include #include -#include -#include +#include static ut64 t9_pre = UT64_MAX; // http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html @@ -63,67 +62,6 @@ static ut64 t9_pre = UT64_MAX; SET_SRC_DST_3_REGS(op); \ } -// ESIL macros: - -// put the sign bit on the stack -#define ES_IS_NEGATIVE(arg) "1," arg ",<<<,1,&" - -// call with delay slot -#define ES_CALL_DR(ra, addr) "pc,4,+," ra ",=," ES_J(addr) -#define ES_CALL_D(addr) ES_CALL_DR("ra", addr) - -// call without delay slot -#define ES_CALL_NDR(ra, addr) "pc," ra ",=," ES_J(addr) -#define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr) - -#define USE_DS 0 -#if USE_DS -// emit ERR trap if executed in a delay slot -#define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,}," -// jump to address -#define ES_J(addr) addr ",SETJT,1,SETD" -#else -#define ES_TRAP_DS() "" -#define ES_J(addr) addr ",pc,=" -#endif - -#define ES_B(x) "0xff," x ",&" -#define ES_H(x) "0xffff," x ",&" -#define ES_W(x) "0xffffffff," x ",&" - -// sign extend 32 -> 64 -#define ES_SIGN32_64(arg) es_sign_n_64(a, op, arg, 32) -#define ES_SIGN16_64(arg) es_sign_n_64(a, op, arg, 16) - -#define ES_ADD_CK32_OVERF(x, y, z) es_add_ck(op, x, y, z, 32) -#define ES_ADD_CK64_OVERF(x, y, z) es_add_ck(op, x, y, z, 64) - -static inline void es_sign_n_64(RzAnalysis *a, RzAnalysisOp *op, const char *arg, int bit) { - if (a->bits == 64) { - rz_strbuf_appendf(&op->esil, ",%d,%s,~,%s,=,", bit, arg, arg); - } else { - rz_strbuf_append(&op->esil, ","); - } -} - -static inline void es_add_ck(RzAnalysisOp *op, const char *a1, const char *a2, const char *re, int bit) { - ut64 mask = 1ULL << (bit - 1); - rz_strbuf_appendf(&op->esil, - "%d,0x%" PFMT64x ",%s,%s,^,&,>>,%d,0x%" PFMT64x ",%s,%s,+,&,>>,|,1,==,$z,?{,$$,1,TRAP,}{,%s,%s,+,%s,=,}", - bit - 2, mask, a1, a2, bit - 1, mask, a1, a2, a1, a2, re); -} - -#define PROTECT_ZERO() \ - if (REG(0)[0] == 'z') { \ - rz_strbuf_appendf(&op->esil, ","); \ - } else - -#define ESIL_LOAD(size) \ - PROTECT_ZERO() { \ - rz_strbuf_appendf(&op->esil, "%s,[" size "],%s,=", \ - ARG(1), REG(0)); \ - } - static void opex(RzStrBuf *buf, csh handle, cs_insn *insn) { int i; PJ *pj = pj_new(); @@ -166,439 +104,6 @@ static void opex(RzStrBuf *buf, csh handle, cs_insn *insn) { pj_free(pj); } -static const char *arg(csh *handle, cs_insn *insn, char *buf, int n) { - *buf = 0; - switch (insn->detail->mips.operands[n].type) { - case MIPS_OP_INVALID: - break; - case MIPS_OP_REG: - sprintf(buf, "%s", - cs_reg_name(*handle, - insn->detail->mips.operands[n].reg)); - break; - case MIPS_OP_IMM: { - st64 x = (st64)insn->detail->mips.operands[n].imm; - sprintf(buf, "%" PFMT64d, x); - } break; - case MIPS_OP_MEM: { - int disp = insn->detail->mips.operands[n].mem.disp; - if (disp < 0) { - sprintf(buf, "%" PFMT64d ",%s,-", - (ut64)-insn->detail->mips.operands[n].mem.disp, - cs_reg_name(*handle, - insn->detail->mips.operands[n].mem.base)); - } else { - sprintf(buf, "0x%" PFMT64x ",%s,+", - (ut64)insn->detail->mips.operands[n].mem.disp, - cs_reg_name(*handle, - insn->detail->mips.operands[n].mem.base)); - } - } break; - } - return buf; -} - -#define ARG(x) (*str[x] != 0) ? str[x] : arg(handle, insn, str[x], x) - -static int analyze_op_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { - char str[8][32] = { { 0 } }; - int i; - - rz_strbuf_init(&op->esil); - rz_strbuf_set(&op->esil, ""); - - if (insn) { - // caching operands - for (i = 0; i < insn->detail->mips.op_count && i < 8; i++) { - *str[i] = 0; - ARG(i); - } - } - - if (insn) { - switch (insn->id) { - case MIPS_INS_NOP: - rz_strbuf_setf(&op->esil, ","); - break; - case MIPS_INS_BREAK: - rz_strbuf_setf(&op->esil, "%" PFMT64d ",%" PFMT64d ",TRAP", (st64)IMM(0), (st64)IMM(0)); - break; - case MIPS_INS_SD: - rz_strbuf_appendf(&op->esil, "%s,%s,=[8]", - ARG(0), ARG(1)); - break; - case MIPS_INS_SW: - case MIPS_INS_SWL: - case MIPS_INS_SWR: - rz_strbuf_appendf(&op->esil, "%s,%s,=[4]", - ARG(0), ARG(1)); - break; - case MIPS_INS_SH: - rz_strbuf_appendf(&op->esil, "%s,%s,=[2]", - ARG(0), ARG(1)); - break; - case MIPS_INS_SWC1: - case MIPS_INS_SWC2: - rz_strbuf_setf(&op->esil, "%s,$", ARG(1)); - break; - case MIPS_INS_SB: - rz_strbuf_appendf(&op->esil, "%s,%s,=[1]", - ARG(0), ARG(1)); - break; - case MIPS_INS_CMP: -#if CS_NEXT_VERSION < 6 - case MIPS_INS_CMPU: - case MIPS_INS_CMPGU: - case MIPS_INS_CMPGDU: -#endif - case MIPS_INS_CMPI: - rz_strbuf_appendf(&op->esil, "%s,%s,==", ARG(1), ARG(0)); - break; - case MIPS_INS_DSRA: - rz_strbuf_appendf(&op->esil, - "%s,%s,>>,31,%s,>>,?{,32,%s,32,-,0xffffffff,<<,0xffffffff,&,<<,}{,0,},|,%s,=", - ARG(2), ARG(1), ARG(1), ARG(2), ARG(0)); - break; -#if CS_NEXT_VERSION < 6 - case MIPS_INS_SHRAV: - case MIPS_INS_SHRAV_R: - case MIPS_INS_SHRA: - case MIPS_INS_SHRA_R: - case MIPS_INS_SRA: - rz_strbuf_appendf(&op->esil, - "0xffffffff,%s,%s,>>,&,31,%s,>>,?{,%s,32,-,0xffffffff,<<,0xffffffff,&,}{,0,},|,%s,=", - ARG(2), ARG(1), ARG(1), ARG(2), ARG(0)); - break; - case MIPS_INS_SHRL: - // suffix 'S' forces conditional flag to be updated - case MIPS_INS_SRLV: - case MIPS_INS_SRL: - rz_strbuf_appendf(&op->esil, "%s,%s,>>,%s,=", ARG(2), ARG(1), ARG(0)); - break; -#endif - case MIPS_INS_SLLV: - case MIPS_INS_SLL: - rz_strbuf_appendf(&op->esil, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0)); - break; - case MIPS_INS_BAL: - case MIPS_INS_JAL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), ARG(0)); - break; - case MIPS_INS_JALR: - case MIPS_INS_JALRS: - if (OPCOUNT() < 2) { - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), ARG(0)); - } else { - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_DR("%s", "%s"), ARG(0), ARG(1)); - } - } - break; - case MIPS_INS_JALRC: // no delay - if (OPCOUNT() < 2) { - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_ND("%s"), ARG(0)); - } else { - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_NDR("%s", "%s"), ARG(0), ARG(1)); - } - } - break; - case MIPS_INS_JRADDIUSP: - // increment stackpointer in X and jump to %ra - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,sp,+=," ES_J("ra"), ARG(0)); - break; - case MIPS_INS_JR: - case MIPS_INS_JRC: - case MIPS_INS_J: - case MIPS_INS_B: // ??? - // jump to address with conditional - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_J("%s"), ARG(0)); - break; - case MIPS_INS_BNE: // bne $s, $t, offset - case MIPS_INS_BNEL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,!,?{," ES_J("%s") ",}", - ARG(0), ARG(1), ARG(2)); - break; - case MIPS_INS_BEQ: - case MIPS_INS_BEQL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,?{," ES_J("%s") ",}", - ARG(0), ARG(1), ARG(2)); - break; -#if CS_NEXT_VERSION < 6 - case MIPS_INS_BZ: -#endif - case MIPS_INS_BEQZ: - case MIPS_INS_BEQZC: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,?{," ES_J("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BNEZ: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,!,?{," ES_J("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BEQZALC: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,?{," ES_CALL_ND("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BLEZ: - case MIPS_INS_BLEZC: - case MIPS_INS_BLEZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{," ES_J("%s") ",BREAK,},", - ARG(0), ARG(1)); - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BGEZ: - case MIPS_INS_BGEZC: - case MIPS_INS_BGEZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BGEZAL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BGEZALC: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_ND("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BGTZALC: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{,BREAK,},", ARG(0)); - rz_strbuf_appendf(&op->esil, "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_ND("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BLTZAL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}", ARG(0), ARG(1)); - break; - case MIPS_INS_BLTZ: - case MIPS_INS_BLTZC: - case MIPS_INS_BLTZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BGTZ: - case MIPS_INS_BGTZC: - case MIPS_INS_BGTZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{,BREAK,},", ARG(0)); - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - ARG(0), ARG(1)); - break; - case MIPS_INS_BTEQZ: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,t,==,$z,?{," ES_J("%s") ",}", ARG(0)); - break; - case MIPS_INS_BTNEZ: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,t,==,$z,!,?{," ES_J("%s") ",}", ARG(0)); - break; -#if CS_NEXT_VERSION < 6 - case MIPS_INS_MOV: -#endif - case MIPS_INS_MOVE: - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "%s,%s,=", ARG(1), REG(0)); - } - break; - case MIPS_INS_MOVZ: - case MIPS_INS_MOVF: - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "0,%s,==,$z,?{,%s,%s,=,}", - ARG(2), ARG(1), REG(0)); - } - break; - case MIPS_INS_MOVT: - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "1,%s,==,$z,?{,%s,%s,=,}", - ARG(2), ARG(1), REG(0)); - } - break; -#if CS_NEXT_VERSION < 6 - case MIPS_INS_FSUB: -#endif - case MIPS_INS_SUB: - case MIPS_INS_SUBU: - case MIPS_INS_DSUB: - case MIPS_INS_DSUBU: - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", - ARG(2), ARG(1), ARG(0)); - } - break; - case MIPS_INS_NEG: -#if CS_NEXT_VERSION < 6 - case MIPS_INS_NEGU: -#endif - rz_strbuf_appendf(&op->esil, "%s,0,-,%s,=,", - ARG(1), ARG(0)); - break; - - /** signed -- sets overflow flag */ - case MIPS_INS_ADD: { - PROTECT_ZERO() { - ES_ADD_CK32_OVERF(ARG(1), ARG(2), ARG(0)); - } - } break; - case MIPS_INS_ADDI: - PROTECT_ZERO() { - ES_ADD_CK32_OVERF(ARG(1), ARG(2), ARG(0)); - } - break; - case MIPS_INS_DADD: - case MIPS_INS_DADDI: - ES_ADD_CK64_OVERF(ARG(1), ARG(2), ARG(0)); - break; - /** unsigned */ - case MIPS_INS_DADDU: - case MIPS_INS_ADDU: - case MIPS_INS_ADDIU: - case MIPS_INS_DADDIU: { - const char *arg0 = ARG(0); - const char *arg1 = ARG(1); - const char *arg2 = ARG(2); - PROTECT_ZERO() { - if (*arg2 == '-') { - rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", - arg2 + 1, arg1, arg0); - } else { - rz_strbuf_appendf(&op->esil, "%s,%s,+,%s,=", - arg2, arg1, arg0); - } - } - } break; - case MIPS_INS_LI: -#if CS_NEXT_VERSION < 6 - case MIPS_INS_LDI: -#endif - rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",%s,=", (ut64)IMM(1), ARG(0)); - break; - case MIPS_INS_LUI: - rz_strbuf_appendf(&op->esil, "0x%" PFMT64x "0000,%s,=", (ut64)IMM(1), ARG(0)); - break; - case MIPS_INS_LB: - op->sign = true; - ESIL_LOAD("1"); - break; - case MIPS_INS_LBU: - // one of these is wrong - ESIL_LOAD("1"); - break; - case MIPS_INS_LW: - case MIPS_INS_LWC1: - case MIPS_INS_LWC2: - case MIPS_INS_LWL: - case MIPS_INS_LWR: - case MIPS_INS_LWU: - case MIPS_INS_LL: - ESIL_LOAD("4"); - break; - - case MIPS_INS_LDL: - case MIPS_INS_LDC1: - case MIPS_INS_LDC2: - case MIPS_INS_LLD: - case MIPS_INS_LD: - ESIL_LOAD("8"); - break; - - case MIPS_INS_LWX: - case MIPS_INS_LH: - case MIPS_INS_LHU: - case MIPS_INS_LHX: - ESIL_LOAD("2"); - break; - - case MIPS_INS_AND: - case MIPS_INS_ANDI: { - const char *arg0 = ARG(0); - const char *arg1 = ARG(1); - const char *arg2 = ARG(2); - if (!strcmp(arg0, arg1)) { - rz_strbuf_appendf(&op->esil, "%s,%s,&=", arg2, arg1); - } else { - rz_strbuf_appendf(&op->esil, "%s,%s,&,%s,=", arg2, arg1, arg0); - } - } break; - case MIPS_INS_OR: - case MIPS_INS_ORI: { - const char *arg0 = ARG(0); - const char *arg1 = ARG(1); - const char *arg2 = ARG(2); - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "%s,%s,|,%s,=", - arg2, arg1, arg0); - } - } break; - case MIPS_INS_XOR: - case MIPS_INS_XORI: { - const char *arg0 = ARG(0); - const char *arg1 = ARG(1); - const char *arg2 = ARG(2); - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "%s,%s,^,%s,=", - arg2, arg1, arg0); - } - } break; - case MIPS_INS_NOR: { - const char *arg0 = ARG(0); - const char *arg1 = ARG(1); - const char *arg2 = ARG(2); - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "%s,%s,|,0xffffffff,^,%s,=", - arg2, arg1, arg0); - } - } break; - case MIPS_INS_SLT: - case MIPS_INS_SLTI: - if (OPCOUNT() < 3) { - rz_strbuf_appendf(&op->esil, "%s,%s,<,t,=", ARG(1), ARG(0)); - } else { - rz_strbuf_appendf(&op->esil, "%s,%s,<,%s,=", ARG(2), ARG(1), ARG(0)); - } - break; - case MIPS_INS_SLTU: - case MIPS_INS_SLTIU: - if (OPCOUNT() < 3) { - rz_strbuf_appendf(&op->esil, ES_W("%s") "," ES_W("%s") ",<,t,=", - ARG(1), ARG(0)); - } else { - rz_strbuf_appendf(&op->esil, ES_W("%s") "," ES_W("%s") ",<,%s,=", - ARG(2), ARG(1), ARG(0)); - } - break; - case MIPS_INS_MUL: - rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",%s,=", ARG(1), ARG(2), ARG(0)); - ES_SIGN32_64(ARG(0)); - break; - case MIPS_INS_MULT: - case MIPS_INS_MULTU: - rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",lo,=", ARG(0), ARG(1)); - ES_SIGN32_64("lo"); - rz_strbuf_appendf(&op->esil, ES_W("32,%s,%s,*,>>") ",hi,=", ARG(0), ARG(1)); - ES_SIGN32_64("hi"); - break; - case MIPS_INS_MFLO: - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "lo,%s,=", REG(0)); - } - break; - case MIPS_INS_MFHI: - PROTECT_ZERO() { - rz_strbuf_appendf(&op->esil, "hi,%s,=", REG(0)); - } - break; - case MIPS_INS_MTLO: - rz_strbuf_appendf(&op->esil, "%s,lo,=", REG(0)); - ES_SIGN32_64("lo"); - break; - case MIPS_INS_MTHI: - rz_strbuf_appendf(&op->esil, "%s,hi,=", REG(0)); - ES_SIGN32_64("hi"); - break; - default: - return -1; - } - } - return 0; -} - static int parse_reg_name(RzRegItem *reg, csh handle, cs_insn *insn, int reg_num) { if (!reg) { return -1; @@ -709,31 +214,11 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u int n = 0, opsize = -1; csh hndl = 0; cs_insn *insn = NULL; - int mode = analysis->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; - - if (analysis->cpu && *analysis->cpu) { - if (!strcmp(analysis->cpu, "micro")) { - mode |= CS_MODE_MICRO; - } else if (!strcmp(analysis->cpu, "r6")) { - mode |= CS_MODE_MIPS32R6; - } else if (!strcmp(analysis->cpu, "v3")) { - mode |= CS_MODE_MIPS3; - } else if (!strcmp(analysis->cpu, "v2")) { - mode |= CS_MODE_MIPS2; - } - } - switch (analysis->bits) { - case 64: - mode |= CS_MODE_MIPS64; - break; - case 32: - mode |= CS_MODE_MIPS32; - break; - default: + cs_mode mode = 0; + if (!cs_mode_from_cpu(analysis->cpu, analysis->features, analysis->bits, analysis->big_endian, &mode)) { return -1; } - // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64 op->addr = addr; if (len < 4) { return -1; @@ -786,12 +271,14 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_LDL: case MIPS_INS_LDR: case MIPS_INS_LDXC1: + op->delay = 1; op->type = RZ_ANALYSIS_OP_TYPE_LOAD; if (!op->refptr) { op->refptr = 8; } switch (OPERAND(1).type) { case MIPS_OP_MEM: +#if CS_NEXT_VERSION < 6 if (OPERAND(1).mem.base == MIPS_REG_GP) { op->ptr = analysis->gp + OPERAND(1).mem.disp; if (REGID(0) == MIPS_REG_T9) { @@ -800,6 +287,19 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u } else if (REGID(0) == MIPS_REG_T9) { t9_pre = UT64_MAX; } +#else + if (OPERAND(1).mem.base == MIPS_REG_GP || + OPERAND(1).mem.base == MIPS_REG_GP_64) { + op->ptr = analysis->gp + OPERAND(1).mem.disp; + if (REGID(0) == MIPS_REG_T9 || + REGID(0) == MIPS_REG_T9_64) { + t9_pre = op->ptr; + } + } else if (REGID(0) == MIPS_REG_T9 || + REGID(0) == MIPS_REG_T9_64) { + t9_pre = UT64_MAX; + } +#endif break; case MIPS_OP_IMM: op->ptr = OPERAND(1).imm; @@ -809,7 +309,6 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u default: break; } - // TODO: fill break; case MIPS_INS_SD: case MIPS_INS_SW: @@ -820,6 +319,7 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_SWL: case MIPS_INS_SWR: case MIPS_INS_SWXC1: + op->delay = 1; op->type = RZ_ANALYSIS_OP_TYPE_STORE; break; case MIPS_INS_NOP: @@ -831,9 +331,16 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_BREAK: op->type = RZ_ANALYSIS_OP_TYPE_TRAP; break; +#if CS_NEXT_VERSION > 5 + case MIPS_INS_JALR_HB: + case MIPS_INS_JALRC: + case MIPS_INS_JALRC_HB: + case MIPS_INS_JALRS: + case MIPS_INS_JALRS16: +#endif /* CS_NEXT_VERSION */ case MIPS_INS_JALR: - op->type = RZ_ANALYSIS_OP_TYPE_UCALL; op->delay = 1; + op->type = RZ_ANALYSIS_OP_TYPE_UCALL; #if CS_NEXT_VERSION < 6 if (REGID(0) == MIPS_REG_25) { op->jump = t9_pre; @@ -849,40 +356,56 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u } #endif break; +#if CS_NEXT_VERSION >= 6 + case MIPS_INS_JRCADDIUSP: + op->delay = 0; + op->type = RZ_ANALYSIS_OP_TYPE_CALL; + op->jump = IMM(0); + break; +#endif case MIPS_INS_JAL: case MIPS_INS_JALS: case MIPS_INS_JALX: case MIPS_INS_JRADDIUSP: case MIPS_INS_BAL: - // (no blezal/bgtzal or blezall/bgtzall, only blezalc/bgtzalc) - case MIPS_INS_BLTZAL: // Branch on <0 and link + op->delay = 1; + op->type = RZ_ANALYSIS_OP_TYPE_CALL; + op->jump = IMM(0); + break; + case MIPS_INS_JIALC: + op->delay = 0; + op->type = RZ_ANALYSIS_OP_TYPE_CALL; + op->jump = IMM(0); + break; case MIPS_INS_BGEZAL: // Branch on >=0 and link + case MIPS_INS_BLTZAL: // Branch on <0 and link case MIPS_INS_BLTZALL: // "likely" versions case MIPS_INS_BGEZALL: - case MIPS_INS_BLTZALC: // compact versions - case MIPS_INS_BLEZALC: + op->delay = 1; + if (OPERAND(0).type == MIPS_OP_IMM) { + // this is a JAL + op->jump = IMM(0); + op->type = RZ_ANALYSIS_OP_TYPE_CALL; + } else { + op->jump = IMM(1); + op->fail = addr + (insn->size << 1); + op->type = RZ_ANALYSIS_OP_TYPE_CCALL; + } + break; case MIPS_INS_BGEZALC: + case MIPS_INS_BLTZALC: + case MIPS_INS_BLEZALC: case MIPS_INS_BGTZALC: - case MIPS_INS_JIALC: - case MIPS_INS_JIC: - op->type = RZ_ANALYSIS_OP_TYPE_CALL; - op->jump = IMM(0); - - switch (insn->id) { - case MIPS_INS_JIALC: - case MIPS_INS_JIC: - case MIPS_INS_BLTZALC: - case MIPS_INS_BLEZALC: - case MIPS_INS_BGEZALC: - case MIPS_INS_BGTZALC: - // compact versions (no delay) - op->delay = 0; - op->fail = addr + 4; - break; - default: - op->delay = 1; - op->fail = addr + 8; - break; + // compact versions + op->delay = 0; + if (OPERAND(0).type == MIPS_OP_IMM) { + // this is a JAL + op->jump = IMM(0); + op->type = RZ_ANALYSIS_OP_TYPE_CALL; + } else { + op->jump = IMM(1); + op->fail = addr + (insn->size << 1); + op->type = RZ_ANALYSIS_OP_TYPE_CCALL; } break; case MIPS_INS_LI: @@ -901,7 +424,7 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_DADDI: case MIPS_INS_DADDIU: SET_VAL(op, 2); - op->sign = (insn->id == MIPS_INS_ADDI || insn->id == MIPS_INS_ADD); + op->sign = (insn->id == MIPS_INS_ADDI || insn->id == MIPS_INS_ADD || insn->id == MIPS_INS_DADD); op->type = RZ_ANALYSIS_OP_TYPE_ADD; if (REGID(0) == MIPS_REG_T9) { t9_pre += IMM(2); @@ -911,6 +434,10 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u op->stackptr = -IMM(2); } break; + case MIPS_INS_SUB: + case MIPS_INS_SUBU: + case MIPS_INS_DSUBU: + case MIPS_INS_DSUB: #if CS_NEXT_VERSION < 6 case MIPS_INS_SUBV: case MIPS_INS_SUBVI: @@ -920,11 +447,30 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_SUBS_U: case MIPS_INS_SUBUH: case MIPS_INS_SUBUH_R: -#endif - case MIPS_INS_SUB: - case MIPS_INS_DSUBU: - case MIPS_INS_SUBU: - case MIPS_INS_DSUB: +#else + case MIPS_INS_SUBV_B: + case MIPS_INS_SUBV_D: + case MIPS_INS_SUBV_H: + case MIPS_INS_SUBV_W: + case MIPS_INS_SUBVI_B: + case MIPS_INS_SUBVI_D: + case MIPS_INS_SUBVI_H: + case MIPS_INS_SUBVI_W: + case MIPS_INS_FSUB_D: + case MIPS_INS_FSUB_W: + case MIPS_INS_FMSUB_D: + case MIPS_INS_FMSUB_W: + case MIPS_INS_SUBS_S_B: + case MIPS_INS_SUBS_S_D: + case MIPS_INS_SUBS_S_H: + case MIPS_INS_SUBS_S_W: + case MIPS_INS_SUBS_U_B: + case MIPS_INS_SUBS_U_D: + case MIPS_INS_SUBS_U_H: + case MIPS_INS_SUBS_U_W: + case MIPS_INS_SUBUH_QB: + case MIPS_INS_SUBUH_R_QB: +#endif /* CS_NEXT_VERSION */ SET_VAL(op, 2); op->sign = insn->id == MIPS_INS_SUB; op->type = RZ_ANALYSIS_OP_TYPE_SUB; @@ -933,7 +479,16 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_MULV: case MIPS_INS_MULSA: case MIPS_INS_FMUL: -#endif +#else + case MIPS_INS_MULV_B: + case MIPS_INS_MULV_D: + case MIPS_INS_MULV_H: + case MIPS_INS_MULV_W: + case MIPS_INS_MULSA_W_PH: + case MIPS_INS_MULSAQ_S_W_PH: + case MIPS_INS_FMUL_D: + case MIPS_INS_FMUL_W: +#endif /* CS_NEXT_VERSION */ case MIPS_INS_MULT: case MIPS_INS_MUL: case MIPS_INS_DMULT: @@ -965,28 +520,149 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_DIVU: case MIPS_INS_DDIV: case MIPS_INS_DDIVU: - case MIPS_INS_DIV_S: #if CS_NEXT_VERSION < 6 case MIPS_INS_FDIV: case MIPS_INS_DIV_U: -#endif +#else + case MIPS_INS_FDIV_D: + case MIPS_INS_FDIV_W: + case MIPS_INS_DIV_U_B: + case MIPS_INS_DIV_U_D: + case MIPS_INS_DIV_U_H: + case MIPS_INS_DIV_U_W: +#endif /* CS_NEXT_VERSION */ + case MIPS_INS_DIV_S: op->type = RZ_ANALYSIS_OP_TYPE_DIV; break; #if CS_NEXT_VERSION < 6 - case MIPS_INS_CMPGDU: - case MIPS_INS_CMPGU: case MIPS_INS_CMPU: -#endif + case MIPS_INS_CMPGU: + case MIPS_INS_CMPGDU: +#else + case MIPS_INS_CMPU_EQ_QB: + case MIPS_INS_CMPGU_EQ_QB: + case MIPS_INS_CMPGDU_EQ_QB: +#endif /* CS_NEXT_VERSION */ case MIPS_INS_CMPI: + case MIPS_INS_CMP: op->type = RZ_ANALYSIS_OP_TYPE_CMP; break; + case MIPS_INS_JIC: + op->delay = 0; + op->jump = IMM(0); + op->type = RZ_ANALYSIS_OP_TYPE_JMP; + break; + case MIPS_INS_J: + op->delay = 1; + op->jump = IMM(0); + op->type = RZ_ANALYSIS_OP_TYPE_JMP; + break; #if CS_NEXT_VERSION < 6 case MIPS_INS_BZ: case MIPS_INS_BNZ: case MIPS_INS_BNEG: case MIPS_INS_BNEGI: -#endif - case MIPS_INS_J: +#else + case MIPS_INS_BZ_B: + case MIPS_INS_BZ_D: + case MIPS_INS_BZ_H: + case MIPS_INS_BZ_V: + case MIPS_INS_BZ_W: + case MIPS_INS_BNZ_B: + case MIPS_INS_BNZ_D: + case MIPS_INS_BNZ_H: + case MIPS_INS_BNZ_V: + case MIPS_INS_BNZ_W: + case MIPS_INS_BNEG_B: + case MIPS_INS_BNEG_D: + case MIPS_INS_BNEG_H: + case MIPS_INS_BNEG_W: + case MIPS_INS_BNEGI_B: + case MIPS_INS_BNEGI_D: + case MIPS_INS_BNEGI_H: + case MIPS_INS_BNEGI_W: + case MIPS_INS_BGE: + case MIPS_INS_BGEL: + case MIPS_INS_BGEU: + case MIPS_INS_BGEUL: + case MIPS_INS_BGT: + case MIPS_INS_BGTL: + case MIPS_INS_BGTU: + case MIPS_INS_BGTUL: + case MIPS_INS_BLE: + case MIPS_INS_BLEL: + case MIPS_INS_BLEU: + case MIPS_INS_BLEUL: + case MIPS_INS_BLT: + case MIPS_INS_BLTL: + case MIPS_INS_BLTU: + case MIPS_INS_BLTUL: + case MIPS_INS_B16: + case MIPS_INS_BADDU: + case MIPS_INS_BALC: + case MIPS_INS_BALIGN: + case MIPS_INS_BALRSC: + case MIPS_INS_BBEQZC: + case MIPS_INS_BBIT0: + case MIPS_INS_BBIT032: + case MIPS_INS_BBIT1: + case MIPS_INS_BBIT132: + case MIPS_INS_BBNEZC: + case MIPS_INS_BC: + case MIPS_INS_BC16: + case MIPS_INS_BC1EQZ: + case MIPS_INS_BC1EQZC: + case MIPS_INS_BC1F: + case MIPS_INS_BC1FL: + case MIPS_INS_BC1NEZ: + case MIPS_INS_BC1NEZC: + case MIPS_INS_BC1T: + case MIPS_INS_BC1TL: + case MIPS_INS_BC2EQZ: + case MIPS_INS_BC2EQZC: + case MIPS_INS_BC2NEZ: + case MIPS_INS_BC2NEZC: + case MIPS_INS_BCLRI_B: + case MIPS_INS_BCLRI_D: + case MIPS_INS_BCLRI_H: + case MIPS_INS_BCLRI_W: + case MIPS_INS_BCLR_B: + case MIPS_INS_BCLR_D: + case MIPS_INS_BCLR_H: + case MIPS_INS_BCLR_W: + case MIPS_INS_BEQC: + case MIPS_INS_BEQIC: + case MIPS_INS_BEQZ16: + case MIPS_INS_BEQZALC: + case MIPS_INS_BEQZC: + case MIPS_INS_BEQZC16: + case MIPS_INS_BGEC: + case MIPS_INS_BGEIC: + case MIPS_INS_BGEIUC: + case MIPS_INS_BGEUC: + case MIPS_INS_BGEZALS: + case MIPS_INS_BLTC: + case MIPS_INS_BLTIC: + case MIPS_INS_BLTIUC: + case MIPS_INS_BLTUC: + case MIPS_INS_BLTZALS: + case MIPS_INS_BMNZI_B: + case MIPS_INS_BMNZ_V: + case MIPS_INS_BMZI_B: + case MIPS_INS_BMZ_V: + case MIPS_INS_BNEC: + case MIPS_INS_BNEIC: + case MIPS_INS_BNEZ16: + case MIPS_INS_BNEZALC: + case MIPS_INS_BNEZC: + case MIPS_INS_BNEZC16: + case MIPS_INS_BNVC: + case MIPS_INS_BOVC: + case MIPS_INS_BPOSGE32: + case MIPS_INS_BPOSGE32C: + case MIPS_INS_BREAK16: + case MIPS_INS_BRSC: +#endif /* CS_NEXT_VERSION */ case MIPS_INS_B: case MIPS_INS_BEQ: case MIPS_INS_BNE: @@ -1008,12 +684,6 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_BGEZC: case MIPS_INS_BLTZC: case MIPS_INS_BGTZC: - if (insn->id == MIPS_INS_J || insn->id == MIPS_INS_B) { - op->type = RZ_ANALYSIS_OP_TYPE_JMP; - } else { - op->type = RZ_ANALYSIS_OP_TYPE_CJMP; - } - if (OPERAND(0).type == MIPS_OP_IMM) { op->jump = IMM(0); } else if (OPERAND(1).type == MIPS_OP_IMM) { @@ -1021,27 +691,81 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u } else if (OPERAND(2).type == MIPS_OP_IMM) { op->jump = IMM(2); } + op->fail = addr + insn->size; + op->type = RZ_ANALYSIS_OP_TYPE_CJMP; + op->delay = 1; switch (insn->id) { +#if CS_NEXT_VERSION >= 6 + case MIPS_INS_B16: +#endif + case MIPS_INS_B: + op->fail = UT64_MAX; + op->type = RZ_ANALYSIS_OP_TYPE_JMP; + break; + case MIPS_INS_BEQ: + if (OPCOUNT() == 1) { + // BEQ $zero $zero is B + op->fail = UT64_MAX; + op->type = RZ_ANALYSIS_OP_TYPE_JMP; + } + break; +#if CS_NEXT_VERSION >= 6 + case MIPS_INS_BALC: + case MIPS_INS_BC16: + case MIPS_INS_BEQC: + case MIPS_INS_BEQIC: + case MIPS_INS_BEQZALC: + case MIPS_INS_BEQZC: + case MIPS_INS_BGEC: + case MIPS_INS_BGEIC: + case MIPS_INS_BGEIUC: + case MIPS_INS_BGEUC: + case MIPS_INS_BLTC: + case MIPS_INS_BLTIC: + case MIPS_INS_BLTIUC: + case MIPS_INS_BLTUC: + case MIPS_INS_BNEC: + case MIPS_INS_BNEIC: + case MIPS_INS_BNEZALC: + case MIPS_INS_BNEZC: + case MIPS_INS_BNVC: + case MIPS_INS_BOVC: + case MIPS_INS_BRSC: + case MIPS_INS_BEQZC16: + case MIPS_INS_BNEZC16: +#endif case MIPS_INS_BLEZC: case MIPS_INS_BGEZC: case MIPS_INS_BLTZC: case MIPS_INS_BGTZC: // compact versions (no delay) op->delay = 0; - op->fail = addr + 4; break; default: - op->delay = 1; - op->fail = addr + 8; break; } break; +#if CS_NEXT_VERSION >= 6 + case MIPS_INS_JRC16: + case MIPS_INS_JR16: + case MIPS_INS_JR_HB: +#endif case MIPS_INS_JR: case MIPS_INS_JRC: +#if CS_NEXT_VERSION < 6 + if (insn->id == MIPS_INS_JRC) { +#else + if (insn->id == MIPS_INS_JRC || + insn->id == MIPS_INS_JRC16) { +#endif + // compact versions (no delay) + op->delay = 0; + } else { + op->delay = 1; + } op->type = RZ_ANALYSIS_OP_TYPE_RJMP; - op->delay = 1; // register is $ra, so jmp is a return if (insn->detail->mips.operands[0].reg == MIPS_REG_RA) { op->type = RZ_ANALYSIS_OP_TYPE_RET; @@ -1049,17 +773,13 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u } #if CS_NEXT_VERSION < 6 if (REGID(0) == MIPS_REG_25) { - op->jump = t9_pre; - t9_pre = UT64_MAX; - } #else if (REGID(0) == MIPS_REG_T9 || REGID(0) == MIPS_REG_T9_64) { +#endif op->jump = t9_pre; t9_pre = UT64_MAX; - op->type = RZ_ANALYSIS_OP_TYPE_RCALL; } -#endif break; case MIPS_INS_SLT: @@ -1070,24 +790,67 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u case MIPS_INS_SLTIU: SET_VAL(op, 2); break; + case MIPS_INS_SRA: #if CS_NEXT_VERSION < 6 case MIPS_INS_SHRAV: case MIPS_INS_SHRAV_R: case MIPS_INS_SHRA: case MIPS_INS_SHRA_R: - case MIPS_INS_SRA: +#else + case MIPS_INS_SHRA_PH: + case MIPS_INS_SHRA_QB: + case MIPS_INS_SHRA_R_PH: + case MIPS_INS_SHRA_R_QB: + case MIPS_INS_SHRA_R_W: + case MIPS_INS_SHRAV_PH: + case MIPS_INS_SHRAV_QB: + case MIPS_INS_SHRAV_R_PH: + case MIPS_INS_SHRAV_R_QB: + case MIPS_INS_SHRAV_R_W: + case MIPS_INS_SRA_B: + case MIPS_INS_SRA_D: + case MIPS_INS_SRA_H: + case MIPS_INS_SRA_W: + case MIPS_INS_SRAI_B: + case MIPS_INS_SRAI_D: + case MIPS_INS_SRAI_H: + case MIPS_INS_SRAI_W: + case MIPS_INS_SRAR_B: + case MIPS_INS_SRAR_D: + case MIPS_INS_SRAR_H: + case MIPS_INS_SRAR_W: + case MIPS_INS_SRARI_B: + case MIPS_INS_SRARI_D: + case MIPS_INS_SRARI_H: + case MIPS_INS_SRARI_W: + case MIPS_INS_SRAV: +#endif /* CS_NEXT_VERSION */ op->type = RZ_ANALYSIS_OP_TYPE_SAR; SET_VAL(op, 2); break; +#if CS_NEXT_VERSION < 6 case MIPS_INS_SHRL: - case MIPS_INS_SRL: -#endif +#else + case MIPS_INS_SHRL_PH: + case MIPS_INS_SHRL_QB: + case MIPS_INS_SHRLV_PH: + case MIPS_INS_SHRLV_QB: +#endif /* CS_NEXT_VERSION */ case MIPS_INS_SRLV: + case MIPS_INS_SRL: op->type = RZ_ANALYSIS_OP_TYPE_SHR; SET_VAL(op, 2); break; case MIPS_INS_SLLV: case MIPS_INS_SLL: +#if CS_NEXT_VERSION >= 6 + op->delay = 0; + if (REGID(0) == MIPS_REG_INVALID) { + // NOP + op->type = RZ_ANALYSIS_OP_TYPE_NOP; + break; + } +#endif /* CS_NEXT_VERSION */ op->type = RZ_ANALYSIS_OP_TYPE_SHL; SET_VAL(op, 2); break; @@ -1220,11 +983,13 @@ static char *get_reg_profile(RzAnalysis *analysis) { static int archinfo(RzAnalysis *a, RzAnalysisInfoType query) { switch (query) { case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE: - /* fall-thru */ + // mips-16, micromips, nanomips uses 16-bits + return 2; case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE: - /* fall-thru */ + // nanomips uses 48-bits + return 6; case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN: - /* fall-thru */ + return 2; case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN: return 4; case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS: @@ -1249,7 +1014,7 @@ static bool mips_fini(void *user) { return true; } -RzAnalysisPlugin rz_analysis_plugin_mips_cs = { +RzAnalysisPlugin rz_analysis_plugin_mips = { .name = "mips", .desc = "Capstone MIPS analyzer", .license = "BSD", @@ -1267,7 +1032,7 @@ RzAnalysisPlugin rz_analysis_plugin_mips_cs = { #ifndef RZ_PLUGIN_INCORE RZ_API RzLibStruct rizin_plugin = { .type = RZ_LIB_TYPE_ANALYSIS, - .data = &rz_analysis_plugin_mips_cs, + .data = &rz_analysis_plugin_mips, .version = RZ_VERSION }; #endif diff --git a/librz/arch/p/arch_mips.c b/librz/arch/p/arch_mips.c new file mode 100644 index 00000000000..376ec446fd4 --- /dev/null +++ b/librz/arch/p/arch_mips.c @@ -0,0 +1,165 @@ +// SPDX-FileCopyrightText: 2024 RizinOrg +// SPDX-FileCopyrightText: 2024 deroad +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include + +#define EXTRA_CPUS "r2300,r2600,r2800,r2000a,r2000,r3000a,r3000,r10000" + +#if CS_NEXT_VERSION < 6 +#define CAPSTONE_CPUS "micromips,mips1,mips2,mips3,mips4,mips16,mips32,mips32r6,mips64" +#define CAPSTONE_FEATURES "" +#else +#define CAPSTONE_CPUS "micromips,mips1,mips2,mips32r2,mips32r3,mips32r5,mips32r6,mips3,mips4,mips5,mips64r2,mips64r3,mips64r5,mips64r6,octeon,octeonp,nanomips,nms1,i7200,micro32r3,micro32r6" +#define CAPSTONE_FEATURES "noptr64,nofloat" +#endif + +#define MIPS_CPUS CAPSTONE_CPUS "," EXTRA_CPUS +#define MIPS_FEATURES CAPSTONE_FEATURES + +#define return_on_cpu(cpu_name, mode_flag) \ + do { \ + if (!strcmp(cpu, cpu_name)) { \ + *mode = _mode | mode_flag; \ + return true; \ + } \ + } while (0) + +static bool cs_mode_from_cpu(const char *cpu, const char *features, int bits, bool big_endian, cs_mode *mode) { + cs_mode _mode = (big_endian) ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; +#if CS_NEXT_VERSION < 6 + + (void)features; + + switch (bits) { + case 64: + _mode |= CS_MODE_MIPS64; + break; + case 32: + _mode |= CS_MODE_MIPS32; + break; + default: + return false; + } + *mode = _mode; + + if (RZ_STR_ISNOTEMPTY(cpu)) { + return_on_cpu("micromips", CS_MODE_MICRO); + return_on_cpu("mips1", CS_MODE_MIPS2); // mips1 is subset of mips2 + return_on_cpu("mips2", CS_MODE_MIPS2); + return_on_cpu("mips3", CS_MODE_MIPS3); + return_on_cpu("mips4", CS_MODE_MIPS32); // old capstone uses the same + return_on_cpu("mips16", CS_MODE_MIPS32); // old capstone uses the same + return_on_cpu("mips32", CS_MODE_MIPS32); + return_on_cpu("mips32r6", CS_MODE_MIPS32R6); + return_on_cpu("mips64", CS_MODE_MIPS64); + return_on_cpu("mips64r2", CS_MODE_MIPS64); // fallback to mips64 + return_on_cpu("mips64r3", CS_MODE_MIPS64); // fallback to mips64 + return_on_cpu("mips64r5", CS_MODE_MIPS64); // fallback to mips64 + return_on_cpu("mips64r6", CS_MODE_MIPS64); // fallback to mips64 + + // extra cpus + return_on_cpu("r2300", CS_MODE_MIPS2); + return_on_cpu("r2600", CS_MODE_MIPS2); + return_on_cpu("r2800", CS_MODE_MIPS2); + return_on_cpu("r2000a", CS_MODE_MIPS2); + return_on_cpu("r2000", CS_MODE_MIPS2); + return_on_cpu("r3000a", CS_MODE_MIPS2); // ISA mips2 + return_on_cpu("r3000", CS_MODE_MIPS2); // ISA mips2 + return_on_cpu("r10000", CS_MODE_MIPS32); // old capstone uses the same + } + +#else // CS_NEXT_VERSION >= 6 +#define return_or_add_on_cpu(cpu_name, mode_flag) \ + do { \ + if (!strcmp(cpu, cpu_name)) { \ + *mode = _mode | mode_flag; \ + return true; \ + } \ + const size_t cpu_name_len = strlen(cpu_name); \ + const char *p = strstr(cpu, cpu_name); \ + if (p && (p[cpu_name_len] == '\0' || p[cpu_name_len] == ' ')) { \ + _add_mode |= mode_flag; \ + } \ + } while (0) + + bool is_noptr64 = RZ_STR_ISNOTEMPTY(features) && strstr(features, "noptr64"); + if (!is_noptr64 && bits > 16) { + _mode |= CS_MODE_MIPS_PTR64; + } + + bool is_nofloat = RZ_STR_ISNOTEMPTY(features) && strstr(features, "nofloat"); + if (is_nofloat) { + _mode |= CS_MODE_MIPS_NOFLOAT; + } + + if (RZ_STR_ISNOTEMPTY(cpu)) { + cs_mode _add_mode = 0; + return_or_add_on_cpu("micromips", CS_MODE_MICRO); + return_or_add_on_cpu("mips1", CS_MODE_MIPS1); + return_or_add_on_cpu("mips2", CS_MODE_MIPS2); + return_or_add_on_cpu("mips16", CS_MODE_MIPS16); + return_or_add_on_cpu("mips32", CS_MODE_MIPS3); // we always map the generic mips32 as mips3 + return_or_add_on_cpu("mips32r2", CS_MODE_MIPS32R2); + return_or_add_on_cpu("mips32r3", CS_MODE_MIPS32R3); + return_or_add_on_cpu("mips32r5", CS_MODE_MIPS32R5); + return_or_add_on_cpu("mips32r6", CS_MODE_MIPS32R6); + return_or_add_on_cpu("mips3", CS_MODE_MIPS3); + return_or_add_on_cpu("mips4", CS_MODE_MIPS4); + return_or_add_on_cpu("mips5", CS_MODE_MIPS5); + return_or_add_on_cpu("mips64", CS_MODE_MIPS64); + return_or_add_on_cpu("mips64r2", CS_MODE_MIPS64); // fallback to mips64 + return_or_add_on_cpu("mips64r3", CS_MODE_MIPS64R3); + return_or_add_on_cpu("mips64r5", CS_MODE_MIPS64R5); + return_or_add_on_cpu("mips64r6", CS_MODE_MIPS64R6); + return_or_add_on_cpu("octeon", CS_MODE_OCTEON); + return_or_add_on_cpu("octeonp", CS_MODE_OCTEONP); + return_or_add_on_cpu("nanomips", CS_MODE_NANOMIPS); + return_or_add_on_cpu("nms1", CS_MODE_NMS1); + return_or_add_on_cpu("i7200", CS_MODE_I7200); +#undef return_or_add_on_cpu + + if (_add_mode) { + *mode = _add_mode; + return true; + } + + // special cpus. + return_on_cpu("micro32r3", CS_MODE_MICRO32R3); + return_on_cpu("micro32r6", CS_MODE_MICRO32R6); + + // extra cpus + return_on_cpu("r2300", CS_MODE_MIPS2); + return_on_cpu("r2600", CS_MODE_MIPS2); + return_on_cpu("r2800", CS_MODE_MIPS2); + return_on_cpu("r2000a", CS_MODE_MIPS2); + return_on_cpu("r2000", CS_MODE_MIPS2); + return_on_cpu("r3000a", CS_MODE_MIPS2); // ISA mips2 + return_on_cpu("r3000", CS_MODE_MIPS2); // ISA mips2 + return_on_cpu("r10000", CS_MODE_MIPS4); + } + + switch (bits) { + case 64: // generic mips64 + *mode = _mode | CS_MODE_MIPS64; + break; + case 32: // generic mips32 + *mode = _mode | CS_MODE_MIPS3; + break; + case 16: // generic mips16 + *mode = _mode | CS_MODE_MIPS16; + break; + default: + return false; + } +#endif /* CS_NEXT_VERSION */ + return true; +} +#undef return_on_cpu + +#include "analysis/analysis_mips.c" +#include "asm/asm_mips.c" +#include "parse/parse_mips_pseudo.c" + +RZ_ARCH_WITH_PARSE_PLUGIN_DEFINE_DEPRECATED(mips); diff --git a/librz/arch/p/arch_mips_cs.c b/librz/arch/p/arch_mips_cs.c deleted file mode 100644 index 17e9614c4dd..00000000000 --- a/librz/arch/p/arch_mips_cs.c +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2024 RizinOrg -// SPDX-FileCopyrightText: 2024 deroad -// SPDX-License-Identifier: LGPL-3.0-only - -#include - -#include "analysis/analysis_mips_cs.c" -#include "asm/asm_mips_cs.c" -#include "parse/parse_mips_pseudo.c" - -RZ_ARCH_WITH_PARSE_PLUGIN_DEFINE_DEPRECATED(mips_cs); diff --git a/librz/arch/p/asm/asm_avr.c b/librz/arch/p/asm/asm_avr.c index 0cb20f4ceac..f3c27686400 100644 --- a/librz/arch/p/asm/asm_avr.c +++ b/librz/arch/p/asm/asm_avr.c @@ -61,5 +61,5 @@ RzAsmPlugin rz_asm_plugin_avr = { "ATmega88," "ATxmega128a4u," "ATTiny48," - "ATTiny88," + "ATTiny88" }; diff --git a/librz/arch/p/asm/asm_luac.c b/librz/arch/p/asm/asm_luac.c index 30021525f76..bf2fa8b3277 100644 --- a/librz/arch/p/asm/asm_luac.c +++ b/librz/arch/p/asm/asm_luac.c @@ -60,6 +60,7 @@ RzAsmPlugin rz_asm_plugin_luac = { .name = "luac", .arch = "luac", .license = "LGPL3", + .cpus = "5.3,5.4", .bits = 8, .desc = "luac disassemble plugin", .disassemble = &rz_luac_disasm, diff --git a/librz/arch/p/asm/asm_mips_cs.c b/librz/arch/p/asm/asm_mips.c similarity index 74% rename from librz/arch/p/asm/asm_mips_cs.c rename to librz/arch/p/asm/asm_mips.c index 94c675c24c4..fc5b74d0e13 100644 --- a/librz/arch/p/asm/asm_mips_cs.c +++ b/librz/arch/p/asm/asm_mips.c @@ -3,7 +3,8 @@ #include #include -#include +#include +#include #include "cs_helper.h" CAPSTONE_DEFINE_PLUGIN_FUNCTIONS(mips_asm); @@ -12,23 +13,17 @@ static int mips_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { CapstoneContext *ctx = (CapstoneContext *)a->plugin_data; cs_insn *insn; - int mode, n, ret = -1; - mode = (a->big_endian) ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; + cs_mode mode = 0; + int n, ret = -1; if (!op) { return 0; } - if (a->cpu && *a->cpu) { - if (!strcmp(a->cpu, "micro")) { - mode |= CS_MODE_MICRO; - } else if (!strcmp(a->cpu, "r6")) { - mode |= CS_MODE_MIPS32R6; - } else if (!strcmp(a->cpu, "v3")) { - mode |= CS_MODE_MIPS3; - } else if (!strcmp(a->cpu, "v2")) { - mode |= CS_MODE_MIPS2; - } + + if (!cs_mode_from_cpu(a->cpu, a->features, a->bits, a->big_endian, &mode)) { + rz_asm_op_set_asm(op, "invalid"); + return -1; } - mode |= (a->bits == 64) ? CS_MODE_MIPS64 : CS_MODE_MIPS32; + memset(op, 0, sizeof(RzAsmOp)); op->size = 4; if (ctx->omode != mode) { @@ -39,10 +34,14 @@ static int mips_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { if (!ctx->handle) { ret = cs_open(CS_ARCH_MIPS, mode, &ctx->handle); if (ret) { + RZ_LOG_ERROR("failed to open capstone\n"); goto fin; } ctx->omode = mode; cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_OFF); +#if CS_NEXT_VERSION > 5 + cs_option(ctx->handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NO_DOLLAR); +#endif } if (a->syntax == RZ_ASM_SYNTAX_REGNUM) { cs_option(ctx->handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); @@ -52,7 +51,11 @@ static int mips_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { n = cs_disasm(ctx->handle, (ut8 *)buf, len, a->pc, 1, &insn); if (n < 1) { rz_asm_op_set_asm(op, "invalid"); - op->size = 4; +#if CS_NEXT_VERSION < 6 + op->size = mode & CS_MODE_MICRO ? 2 : 4; +#else + op->size = mode & (CS_MODE_MICRO | CS_MODE_NANOMIPS | CS_MODE_MIPS16) ? 2 : 4; +#endif goto fin; } if (insn->size < 1) { @@ -60,11 +63,15 @@ static int mips_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { } op->size = insn->size; rz_asm_op_setf_asm(op, "%s%s%s", insn->mnemonic, insn->op_str[0] ? " " : "", insn->op_str); + +#if CS_NEXT_VERSION < 6 + // CS_OPT_SYNTAX_NO_DOLLAR is not available before capstone 6 char *str = rz_asm_op_get_asm(op); if (str) { // remove the '$' in the string rz_str_replace_char(str, '$', 0); } +#endif cs_free(insn, n); fin: return op->size; @@ -85,12 +92,13 @@ static int mips_assemble(RzAsm *a, RzAsmOp *op, const char *str) { return ret; } -RzAsmPlugin rz_asm_plugin_mips_cs = { +RzAsmPlugin rz_asm_plugin_mips = { .name = "mips", .desc = "Capstone MIPS disassembler", .license = "BSD", .arch = "mips", - .cpus = "mips32/64,micro,r6,v3,v2", + .cpus = MIPS_CPUS, + .features = MIPS_FEATURES, .bits = 16 | 32 | 64, .endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG, .init = mips_asm_init, @@ -103,7 +111,7 @@ RzAsmPlugin rz_asm_plugin_mips_cs = { #ifndef RZ_PLUGIN_INCORE RZ_API RzLibStruct rizin_plugin = { .type = RZ_LIB_TYPE_ASM, - .data = &rz_asm_plugin_mips_cs, + .data = &rz_asm_plugin_mips, .version = RZ_VERSION }; #endif diff --git a/librz/arch/p/parse/parse_mips_pseudo.c b/librz/arch/p/parse/parse_mips_pseudo.c index 8d10c8e15e2..45b4562bd68 100644 --- a/librz/arch/p/parse/parse_mips_pseudo.c +++ b/librz/arch/p/parse/parse_mips_pseudo.c @@ -253,7 +253,7 @@ static bool subvar(RzParse *p, RzAnalysisFunction *f, RzAnalysisOp *op, char *da return ret; } -RzParsePlugin rz_parse_plugin_mips_cs_pseudo = { +RzParsePlugin rz_parse_plugin_mips_pseudo = { .name = "mips.pseudo", .desc = "MIPS pseudo syntax", .init = NULL, diff --git a/librz/arch/p_gnu/analysis/analysis_mips_gnu.c b/librz/arch/p_gnu/analysis/analysis_mips_gnu.c index b925efffddd..8b137891791 100644 --- a/librz/arch/p_gnu/analysis/analysis_mips_gnu.c +++ b/librz/arch/p_gnu/analysis/analysis_mips_gnu.c @@ -1,1800 +1 @@ -// SPDX-FileCopyrightText: 2010-2015 pancake -// SPDX-License-Identifier: LGPL-3.0-only -#include -#include -#include -#include -#include - -static ut64 t9_pre = UT64_MAX; -#define REG_BUF_MAX 32 -// ESIL macros: - -// put the sign bit on the stack -#define ES_IS_NEGATIVE(arg) "1," arg ",<<<,1,&" - -#define ES_B(x) "0xff," x ",&" -#define ES_H(x) "0xffff," x ",&" -#define ES_W(x) "0xffffffff," x ",&" -// call with delay slot -#define ES_CALL_DR(ra, addr) "pc,4,+," ra ",=," ES_J(addr) -#define ES_CALL_D(addr) ES_CALL_DR("ra", addr) - -// call without delay slot -#define ES_CALL_NDR(ra, addr) "pc," ra ",=," ES_J(addr) -#define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr) - -#define USE_DS 0 -#if USE_DS -// emit ERR trap if executed in a delay slot -#define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,}," -// jump to address -#define ES_J(addr) addr ",SETJT,1,SETD" -#else -#define ES_TRAP_DS() "" -#define ES_J(addr) addr ",pc,=" -#endif - -#define ES_SIGN32_64(arg) es_sign_n_64(a, op, arg, 32) -#define ES_SIGN16_64(arg) es_sign_n_64(a, op, arg, 16) - -#define ES_ADD_CK32_OVERF(x, y, z) es_add_ck(op, x, y, z, 32) -#define ES_ADD_CK64_OVERF(x, y, z) es_add_ck(op, x, y, z, 64) - -static inline void es_sign_n_64(RzAnalysis *a, RzAnalysisOp *op, const char *arg, int bit) { - if (a->bits == 64) { - rz_strbuf_appendf(&op->esil, ",%d,%s,~,%s,=,", bit, arg, arg); - } else { - rz_strbuf_append(&op->esil, ","); - } -} - -static inline void es_add_ck(RzAnalysisOp *op, const char *a1, const char *a2, const char *re, int bit) { - ut64 mask = 1ULL << (bit - 1); - rz_strbuf_appendf(&op->esil, - "%d,0x%" PFMT64x ",%s,%s,^,&,>>,%d,0x%" PFMT64x ",%s,%s,+,&,>>,|,1,==,$z,?{,$$,1,TRAP,}{,%s,%s,+,%s,=,}", - bit - 2, mask, a1, a2, bit - 1, mask, a1, a2, a1, a2, re); -} -// MIPS instruction -typedef enum mips_insn { - MIPS_INS_INVALID = 0, - - MIPS_INS_ABSQ_S, - MIPS_INS_ADD, - MIPS_INS_ADDIUPC, - MIPS_INS_ADDIUR1SP, - MIPS_INS_ADDIUR2, - MIPS_INS_ADDIUS5, - MIPS_INS_ADDIUSP, - MIPS_INS_ADDQH, - MIPS_INS_ADDQH_R, - MIPS_INS_ADDQ, - MIPS_INS_ADDQ_S, - MIPS_INS_ADDSC, - MIPS_INS_ADDS_A, - MIPS_INS_ADDS_S, - MIPS_INS_ADDS_U, - MIPS_INS_ADDU16, - MIPS_INS_ADDUH, - MIPS_INS_ADDUH_R, - MIPS_INS_ADDU, - MIPS_INS_ADDU_S, - MIPS_INS_ADDVI, - MIPS_INS_ADDV, - MIPS_INS_ADDWC, - MIPS_INS_ADD_A, - MIPS_INS_ADDI, - MIPS_INS_ADDIU, - MIPS_INS_ALIGN, - MIPS_INS_ALUIPC, - MIPS_INS_AND, - MIPS_INS_AND16, - MIPS_INS_ANDI16, - MIPS_INS_ANDI, - MIPS_INS_APPEND, - MIPS_INS_ASUB_S, - MIPS_INS_ASUB_U, - MIPS_INS_AUI, - MIPS_INS_AUIPC, - MIPS_INS_AVER_S, - MIPS_INS_AVER_U, - MIPS_INS_AVE_S, - MIPS_INS_AVE_U, - MIPS_INS_B16, - MIPS_INS_BADDU, - MIPS_INS_BAL, - MIPS_INS_BALC, - MIPS_INS_BALIGN, - MIPS_INS_BBIT0, - MIPS_INS_BBIT032, - MIPS_INS_BBIT1, - MIPS_INS_BBIT132, - MIPS_INS_BC, - MIPS_INS_BC0F, - MIPS_INS_BC0FL, - MIPS_INS_BC0T, - MIPS_INS_BC0TL, - MIPS_INS_BC1EQZ, - MIPS_INS_BC1F, - MIPS_INS_BC1FL, - MIPS_INS_BC1NEZ, - MIPS_INS_BC1T, - MIPS_INS_BC1TL, - MIPS_INS_BC2EQZ, - MIPS_INS_BC2F, - MIPS_INS_BC2FL, - MIPS_INS_BC2NEZ, - MIPS_INS_BC2T, - MIPS_INS_BC2TL, - MIPS_INS_BC3F, - MIPS_INS_BC3FL, - MIPS_INS_BC3T, - MIPS_INS_BC3TL, - MIPS_INS_BCLRI, - MIPS_INS_BCLR, - MIPS_INS_BEQ, - MIPS_INS_BEQC, - MIPS_INS_BEQL, - MIPS_INS_BEQZ16, - MIPS_INS_BEQZALC, - MIPS_INS_BEQZC, - MIPS_INS_BGEC, - MIPS_INS_BGEUC, - MIPS_INS_BGEZ, - MIPS_INS_BGEZAL, - MIPS_INS_BGEZALC, - MIPS_INS_BGEZALL, - MIPS_INS_BGEZALS, - MIPS_INS_BGEZC, - MIPS_INS_BGEZL, - MIPS_INS_BGTZ, - MIPS_INS_BGTZALC, - MIPS_INS_BGTZC, - MIPS_INS_BGTZL, - MIPS_INS_BINSLI, - MIPS_INS_BINSL, - MIPS_INS_BINSRI, - MIPS_INS_BINSR, - MIPS_INS_BITREV, - MIPS_INS_BITSWAP, - MIPS_INS_BLEZ, - MIPS_INS_BLEZALC, - MIPS_INS_BLEZC, - MIPS_INS_BLEZL, - MIPS_INS_BLTC, - MIPS_INS_BLTUC, - MIPS_INS_BLTZ, - MIPS_INS_BLTZAL, - MIPS_INS_BLTZALC, - MIPS_INS_BLTZALL, - MIPS_INS_BLTZALS, - MIPS_INS_BLTZC, - MIPS_INS_BLTZL, - MIPS_INS_BMNZI, - MIPS_INS_BMNZ, - MIPS_INS_BMZI, - MIPS_INS_BMZ, - MIPS_INS_BNE, - MIPS_INS_BNEC, - MIPS_INS_BNEGI, - MIPS_INS_BNEG, - MIPS_INS_BNEL, - MIPS_INS_BNEZ16, - MIPS_INS_BNEZALC, - MIPS_INS_BNEZC, - MIPS_INS_BNVC, - MIPS_INS_BNZ, - MIPS_INS_BOVC, - MIPS_INS_BPOSGE32, - MIPS_INS_BREAK, - MIPS_INS_BREAK16, - MIPS_INS_BSELI, - MIPS_INS_BSEL, - MIPS_INS_BSETI, - MIPS_INS_BSET, - MIPS_INS_BZ, - MIPS_INS_BEQZ, - MIPS_INS_B, - MIPS_INS_BNEZ, - MIPS_INS_BTEQZ, - MIPS_INS_BTNEZ, - MIPS_INS_CACHE, - MIPS_INS_CEIL, - MIPS_INS_CEQI, - MIPS_INS_CEQ, - MIPS_INS_CFC1, - MIPS_INS_CFCMSA, - MIPS_INS_CINS, - MIPS_INS_CINS32, - MIPS_INS_CLASS, - MIPS_INS_CLEI_S, - MIPS_INS_CLEI_U, - MIPS_INS_CLE_S, - MIPS_INS_CLE_U, - MIPS_INS_CLO, - MIPS_INS_CLTI_S, - MIPS_INS_CLTI_U, - MIPS_INS_CLT_S, - MIPS_INS_CLT_U, - MIPS_INS_CLZ, - MIPS_INS_CMPGDU, - MIPS_INS_CMPGU, - MIPS_INS_CMPU, - MIPS_INS_CMP, - MIPS_INS_COPY_S, - MIPS_INS_COPY_U, - MIPS_INS_CTC1, - MIPS_INS_CTCMSA, - MIPS_INS_CVT, - MIPS_INS_C, - MIPS_INS_CMPI, - MIPS_INS_DADD, - MIPS_INS_DADDI, - MIPS_INS_DADDIU, - MIPS_INS_DADDU, - MIPS_INS_DAHI, - MIPS_INS_DALIGN, - MIPS_INS_DATI, - MIPS_INS_DAUI, - MIPS_INS_DBITSWAP, - MIPS_INS_DCLO, - MIPS_INS_DCLZ, - MIPS_INS_DDIV, - MIPS_INS_DDIVU, - MIPS_INS_DERET, - MIPS_INS_DEXT, - MIPS_INS_DEXTM, - MIPS_INS_DEXTU, - MIPS_INS_DI, - MIPS_INS_DINS, - MIPS_INS_DINSM, - MIPS_INS_DINSU, - MIPS_INS_DIV, - MIPS_INS_DIVU, - MIPS_INS_DIV_S, - MIPS_INS_DIV_U, - MIPS_INS_DLSA, - MIPS_INS_DMFC0, - MIPS_INS_DMFC1, - MIPS_INS_DMFC2, - MIPS_INS_DMOD, - MIPS_INS_DMODU, - MIPS_INS_DMTC0, - MIPS_INS_DMTC1, - MIPS_INS_DMTC2, - MIPS_INS_DMUH, - MIPS_INS_DMUHU, - MIPS_INS_DMUL, - MIPS_INS_DMULT, - MIPS_INS_DMULTU, - MIPS_INS_DMULU, - MIPS_INS_DOTP_S, - MIPS_INS_DOTP_U, - MIPS_INS_DPADD_S, - MIPS_INS_DPADD_U, - MIPS_INS_DPAQX_SA, - MIPS_INS_DPAQX_S, - MIPS_INS_DPAQ_SA, - MIPS_INS_DPAQ_S, - MIPS_INS_DPAU, - MIPS_INS_DPAX, - MIPS_INS_DPA, - MIPS_INS_DPOP, - MIPS_INS_DPSQX_SA, - MIPS_INS_DPSQX_S, - MIPS_INS_DPSQ_SA, - MIPS_INS_DPSQ_S, - MIPS_INS_DPSUB_S, - MIPS_INS_DPSUB_U, - MIPS_INS_DPSU, - MIPS_INS_DPSX, - MIPS_INS_DPS, - MIPS_INS_DROTR, - MIPS_INS_DROTR32, - MIPS_INS_DROTRV, - MIPS_INS_DSBH, - MIPS_INS_DSHD, - MIPS_INS_DSLL, - MIPS_INS_DSLL32, - MIPS_INS_DSLLV, - MIPS_INS_DSRA, - MIPS_INS_DSRA32, - MIPS_INS_DSRAV, - MIPS_INS_DSRL, - MIPS_INS_DSRL32, - MIPS_INS_DSRLV, - MIPS_INS_DSUB, - MIPS_INS_DSUBU, - MIPS_INS_EHB, - MIPS_INS_EI, - MIPS_INS_ERET, - MIPS_INS_EXT, - MIPS_INS_EXTP, - MIPS_INS_EXTPDP, - MIPS_INS_EXTPDPV, - MIPS_INS_EXTPV, - MIPS_INS_EXTRV_RS, - MIPS_INS_EXTRV_R, - MIPS_INS_EXTRV_S, - MIPS_INS_EXTRV, - MIPS_INS_EXTR_RS, - MIPS_INS_EXTR_R, - MIPS_INS_EXTR_S, - MIPS_INS_EXTR, - MIPS_INS_EXTS, - MIPS_INS_EXTS32, - MIPS_INS_ABS, - MIPS_INS_FADD, - MIPS_INS_FCAF, - MIPS_INS_FCEQ, - MIPS_INS_FCLASS, - MIPS_INS_FCLE, - MIPS_INS_FCLT, - MIPS_INS_FCNE, - MIPS_INS_FCOR, - MIPS_INS_FCUEQ, - MIPS_INS_FCULE, - MIPS_INS_FCULT, - MIPS_INS_FCUNE, - MIPS_INS_FCUN, - MIPS_INS_FDIV, - MIPS_INS_FEXDO, - MIPS_INS_FEXP2, - MIPS_INS_FEXUPL, - MIPS_INS_FEXUPR, - MIPS_INS_FFINT_S, - MIPS_INS_FFINT_U, - MIPS_INS_FFQL, - MIPS_INS_FFQR, - MIPS_INS_FILL, - MIPS_INS_FLOG2, - MIPS_INS_FLOOR, - MIPS_INS_FMADD, - MIPS_INS_FMAX_A, - MIPS_INS_FMAX, - MIPS_INS_FMIN_A, - MIPS_INS_FMIN, - MIPS_INS_MOV, - MIPS_INS_FMSUB, - MIPS_INS_FMUL, - MIPS_INS_MUL, - MIPS_INS_NEG, - MIPS_INS_FRCP, - MIPS_INS_FRINT, - MIPS_INS_FRSQRT, - MIPS_INS_FSAF, - MIPS_INS_FSEQ, - MIPS_INS_FSLE, - MIPS_INS_FSLT, - MIPS_INS_FSNE, - MIPS_INS_FSOR, - MIPS_INS_FSQRT, - MIPS_INS_SQRT, - MIPS_INS_FSUB, - MIPS_INS_SUB, - MIPS_INS_FSUEQ, - MIPS_INS_FSULE, - MIPS_INS_FSULT, - MIPS_INS_FSUNE, - MIPS_INS_FSUN, - MIPS_INS_FTINT_S, - MIPS_INS_FTINT_U, - MIPS_INS_FTQ, - MIPS_INS_FTRUNC_S, - MIPS_INS_FTRUNC_U, - MIPS_INS_HADD_S, - MIPS_INS_HADD_U, - MIPS_INS_HSUB_S, - MIPS_INS_HSUB_U, - MIPS_INS_ILVEV, - MIPS_INS_ILVL, - MIPS_INS_ILVOD, - MIPS_INS_ILVR, - MIPS_INS_INS, - MIPS_INS_INSERT, - MIPS_INS_INSV, - MIPS_INS_INSVE, - MIPS_INS_J, - MIPS_INS_JAL, - MIPS_INS_JALR, - MIPS_INS_JALRS16, - MIPS_INS_JALRS, - MIPS_INS_JALS, - MIPS_INS_JALX, - MIPS_INS_JIALC, - MIPS_INS_JIC, - MIPS_INS_JR, - MIPS_INS_JR16, - MIPS_INS_JRADDIUSP, - MIPS_INS_JRC, - MIPS_INS_JALRC, - MIPS_INS_LB, - MIPS_INS_LBU16, - MIPS_INS_LBUX, - MIPS_INS_LBU, - MIPS_INS_LD, - MIPS_INS_LDC1, - MIPS_INS_LDC2, - MIPS_INS_LDC3, - MIPS_INS_LDI, - MIPS_INS_LDL, - MIPS_INS_LDPC, - MIPS_INS_LDR, - MIPS_INS_LDXC1, - MIPS_INS_LH, - MIPS_INS_LHU16, - MIPS_INS_LHX, - MIPS_INS_LHU, - MIPS_INS_LI16, - MIPS_INS_LL, - MIPS_INS_LLD, - MIPS_INS_LSA, - MIPS_INS_LUXC1, - MIPS_INS_LUI, - MIPS_INS_LW, - MIPS_INS_LW16, - MIPS_INS_LWC1, - MIPS_INS_LWC2, - MIPS_INS_LWC3, - MIPS_INS_LWL, - MIPS_INS_LWM16, - MIPS_INS_LWM32, - MIPS_INS_LWPC, - MIPS_INS_LWP, - MIPS_INS_LWR, - MIPS_INS_LWUPC, - MIPS_INS_LWU, - MIPS_INS_LWX, - MIPS_INS_LWXC1, - MIPS_INS_LWXS, - MIPS_INS_LI, - MIPS_INS_MADD, - MIPS_INS_MADDF, - MIPS_INS_MADDR_Q, - MIPS_INS_MADDU, - MIPS_INS_MADDV, - MIPS_INS_MADD_Q, - MIPS_INS_MAQ_SA, - MIPS_INS_MAQ_S, - MIPS_INS_MAXA, - MIPS_INS_MAXI_S, - MIPS_INS_MAXI_U, - MIPS_INS_MAX_A, - MIPS_INS_MAX, - MIPS_INS_MAX_S, - MIPS_INS_MAX_U, - MIPS_INS_MFC0, - MIPS_INS_MFC1, - MIPS_INS_MFC2, - MIPS_INS_MFHC1, - MIPS_INS_MFHI, - MIPS_INS_MFLO, - MIPS_INS_MINA, - MIPS_INS_MINI_S, - MIPS_INS_MINI_U, - MIPS_INS_MIN_A, - MIPS_INS_MIN, - MIPS_INS_MIN_S, - MIPS_INS_MIN_U, - MIPS_INS_MOD, - MIPS_INS_MODSUB, - MIPS_INS_MODU, - MIPS_INS_MOD_S, - MIPS_INS_MOD_U, - MIPS_INS_MOVE, - MIPS_INS_MOVEP, - MIPS_INS_MOVF, - MIPS_INS_MOVN, - MIPS_INS_MOVT, - MIPS_INS_MOVZ, - MIPS_INS_MSUB, - MIPS_INS_MSUBF, - MIPS_INS_MSUBR_Q, - MIPS_INS_MSUBU, - MIPS_INS_MSUBV, - MIPS_INS_MSUB_Q, - MIPS_INS_MTC0, - MIPS_INS_MTC1, - MIPS_INS_MTC2, - MIPS_INS_MTHC1, - MIPS_INS_MTHI, - MIPS_INS_MTHLIP, - MIPS_INS_MTLO, - MIPS_INS_MTM0, - MIPS_INS_MTM1, - MIPS_INS_MTM2, - MIPS_INS_MTP0, - MIPS_INS_MTP1, - MIPS_INS_MTP2, - MIPS_INS_MUH, - MIPS_INS_MUHU, - MIPS_INS_MULEQ_S, - MIPS_INS_MULEU_S, - MIPS_INS_MULQ_RS, - MIPS_INS_MULQ_S, - MIPS_INS_MULR_Q, - MIPS_INS_MULSAQ_S, - MIPS_INS_MULSA, - MIPS_INS_MULT, - MIPS_INS_MULTU, - MIPS_INS_MULU, - MIPS_INS_MULV, - MIPS_INS_MUL_Q, - MIPS_INS_MUL_S, - MIPS_INS_NLOC, - MIPS_INS_NLZC, - MIPS_INS_NMADD, - MIPS_INS_NMSUB, - MIPS_INS_NOR, - MIPS_INS_NORI, - MIPS_INS_NOT16, - MIPS_INS_NOT, - MIPS_INS_OR, - MIPS_INS_OR16, - MIPS_INS_ORI, - MIPS_INS_PACKRL, - MIPS_INS_PAUSE, - MIPS_INS_PCKEV, - MIPS_INS_PCKOD, - MIPS_INS_PCNT, - MIPS_INS_PICK, - MIPS_INS_POP, - MIPS_INS_PRECEQU, - MIPS_INS_PRECEQ, - MIPS_INS_PRECEU, - MIPS_INS_PRECRQU_S, - MIPS_INS_PRECRQ, - MIPS_INS_PRECRQ_RS, - MIPS_INS_PRECR, - MIPS_INS_PRECR_SRA, - MIPS_INS_PRECR_SRA_R, - MIPS_INS_PREF, - MIPS_INS_PREPEND, - MIPS_INS_RADDU, - MIPS_INS_RDDSP, - MIPS_INS_RDHWR, - MIPS_INS_REPLV, - MIPS_INS_REPL, - MIPS_INS_RINT, - MIPS_INS_ROTR, - MIPS_INS_ROTRV, - MIPS_INS_ROUND, - MIPS_INS_SAT_S, - MIPS_INS_SAT_U, - MIPS_INS_SB, - MIPS_INS_SB16, - MIPS_INS_SC, - MIPS_INS_SCD, - MIPS_INS_SD, - MIPS_INS_SDBBP, - MIPS_INS_SDBBP16, - MIPS_INS_SDC1, - MIPS_INS_SDC2, - MIPS_INS_SDC3, - MIPS_INS_SDL, - MIPS_INS_SDR, - MIPS_INS_SDXC1, - MIPS_INS_SEB, - MIPS_INS_SEH, - MIPS_INS_SELEQZ, - MIPS_INS_SELNEZ, - MIPS_INS_SEL, - MIPS_INS_SEQ, - MIPS_INS_SEQI, - MIPS_INS_SH, - MIPS_INS_SH16, - MIPS_INS_SHF, - MIPS_INS_SHILO, - MIPS_INS_SHILOV, - MIPS_INS_SHLLV, - MIPS_INS_SHLLV_S, - MIPS_INS_SHLL, - MIPS_INS_SHLL_S, - MIPS_INS_SHRAV, - MIPS_INS_SHRAV_R, - MIPS_INS_SHRA, - MIPS_INS_SHRA_R, - MIPS_INS_SHRLV, - MIPS_INS_SHRL, - MIPS_INS_SLDI, - MIPS_INS_SLD, - MIPS_INS_SLL, - MIPS_INS_SLL16, - MIPS_INS_SLLI, - MIPS_INS_SLLV, - MIPS_INS_SLT, - MIPS_INS_SLTI, - MIPS_INS_SLTIU, - MIPS_INS_SLTU, - MIPS_INS_SNE, - MIPS_INS_SNEI, - MIPS_INS_SPLATI, - MIPS_INS_SPLAT, - MIPS_INS_SRA, - MIPS_INS_SRAI, - MIPS_INS_SRARI, - MIPS_INS_SRAR, - MIPS_INS_SRAV, - MIPS_INS_SRL, - MIPS_INS_SRL16, - MIPS_INS_SRLI, - MIPS_INS_SRLRI, - MIPS_INS_SRLR, - MIPS_INS_SRLV, - MIPS_INS_SSNOP, - MIPS_INS_ST, - MIPS_INS_SUBQH, - MIPS_INS_SUBQH_R, - MIPS_INS_SUBQ, - MIPS_INS_SUBQ_S, - MIPS_INS_SUBSUS_U, - MIPS_INS_SUBSUU_S, - MIPS_INS_SUBS_S, - MIPS_INS_SUBS_U, - MIPS_INS_SUBU16, - MIPS_INS_SUBUH, - MIPS_INS_SUBUH_R, - MIPS_INS_SUBU, - MIPS_INS_SUBU_S, - MIPS_INS_SUBVI, - MIPS_INS_SUBV, - MIPS_INS_SUXC1, - MIPS_INS_SW, - MIPS_INS_SW16, - MIPS_INS_SWC1, - MIPS_INS_SWC2, - MIPS_INS_SWC3, - MIPS_INS_SWL, - MIPS_INS_SWM16, - MIPS_INS_SWM32, - MIPS_INS_SWP, - MIPS_INS_SWR, - MIPS_INS_SWXC1, - MIPS_INS_SYNC, - MIPS_INS_SYNCI, - MIPS_INS_SYSCALL, - MIPS_INS_TEQ, - MIPS_INS_TEQI, - MIPS_INS_TGE, - MIPS_INS_TGEI, - MIPS_INS_TGEIU, - MIPS_INS_TGEU, - MIPS_INS_TLBP, - MIPS_INS_TLBR, - MIPS_INS_TLBWI, - MIPS_INS_TLBWR, - MIPS_INS_TLT, - MIPS_INS_TLTI, - MIPS_INS_TLTIU, - MIPS_INS_TLTU, - MIPS_INS_TNE, - MIPS_INS_TNEI, - MIPS_INS_TRUNC, - MIPS_INS_V3MULU, - MIPS_INS_VMM0, - MIPS_INS_VMULU, - MIPS_INS_VSHF, - MIPS_INS_WAIT, - MIPS_INS_WRDSP, - MIPS_INS_WSBH, - MIPS_INS_XOR, - MIPS_INS_XOR16, - MIPS_INS_XORI, - - //> some alias instructions - MIPS_INS_NOP, - MIPS_INS_NEGU, - - //> special instructions - MIPS_INS_JALR_HB, // jump and link with Hazard Barrier - MIPS_INS_JR_HB, // jump register with Hazard Barrier - - MIPS_INS_ENDING, -} mips_insn; - -struct gnu_rreg { - const char *rs; - const char *rt; - const char *rd; - ut8 sa[REG_BUF_MAX]; -}; - -struct gnu_jreg { - ut8 jump[REG_BUF_MAX]; -}; - -struct gnu_ireg { - const char *rs; - const char *rt; - union { - ut8 imm[REG_BUF_MAX]; - ut8 jump[REG_BUF_MAX]; - }; -}; - -typedef struct gnu_insn { - ut8 optype; - ut32 id; - union { - struct gnu_rreg r_reg; - struct gnu_ireg i_reg; - struct gnu_jreg j_reg; - }; -} gnu_insn; - -#define R_REG(x) ((const char *)insn->r_reg.x) -#define I_REG(x) ((const char *)insn->i_reg.x) -#define J_REG(x) ((const char *)insn->j_reg.x) - -/* Return a mapping from the register number i.e. $0 .. $31 to string name */ -static const char *mips_reg_decode(ut32 reg_num) { - /* See page 36 of "See Mips Run Linux, 2e, D. Sweetman, 2007"*/ - static const char *REGISTERS[32] = { - "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", "fp", "ra" - }; - if (reg_num < 32) { - return REGISTERS[reg_num]; - } - return NULL; -} - -static int analyze_op_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, gnu_insn *insn) { - - switch (insn->id) { - case MIPS_INS_NOP: - rz_strbuf_setf(&op->esil, ","); - break; - case MIPS_INS_BREAK: - // rz_strbuf_setf (&op->esil, "%d,%d,TRAP", IMM (0), IMM (0)); - break; - case MIPS_INS_SD: - rz_strbuf_appendf(&op->esil, "%s,%s,%s,+,=[8]", - I_REG(rt), I_REG(imm), I_REG(rs)); - break; - case MIPS_INS_SW: - case MIPS_INS_SWL: - case MIPS_INS_SWR: - rz_strbuf_appendf(&op->esil, "%s,%s,%s,+,=[4]", - I_REG(rt), I_REG(imm), I_REG(rs)); - break; - case MIPS_INS_SH: - rz_strbuf_appendf(&op->esil, "%s,%s,%s,+,=[2]", - I_REG(rt), I_REG(imm), I_REG(rs)); - break; - case MIPS_INS_SWC1: - case MIPS_INS_SWC2: - break; - case MIPS_INS_SB: - rz_strbuf_appendf(&op->esil, "%s,%s,%s,+,=[1]", - I_REG(rt), I_REG(imm), I_REG(rs)); - break; - case MIPS_INS_CMP: - case MIPS_INS_CMPU: - case MIPS_INS_CMPGU: - case MIPS_INS_CMPGDU: - case MIPS_INS_CMPI: - break; - case MIPS_INS_SHRAV: - case MIPS_INS_SHRAV_R: - case MIPS_INS_SHRA: - case MIPS_INS_SHRA_R: - break; - case MIPS_INS_SRA: - rz_strbuf_appendf(&op->esil, - ES_W("%s,%s") ",>>,31,%s,>>,?{,%s,32,-,0xffffffff,<<,0xffffffff,&,}{,0,},|,%s,=", - R_REG(sa), R_REG(rt), R_REG(rt), R_REG(sa), R_REG(rd)); - break; - case MIPS_INS_DSRA: - rz_strbuf_appendf(&op->esil, - "%s,%s,>>,31,%s,>>,?{,32,%s,32,-,0xffffffff,<<,0xffffffff,&,<<,}{,0,},|,%s,=", - R_REG(sa), R_REG(rt), R_REG(rt), R_REG(sa), R_REG(rd)); - break; - case MIPS_INS_SHRL: - // suffix 'S' forces conditional flag to be updated - break; - case MIPS_INS_SRLV: - case MIPS_INS_SRL: - rz_strbuf_appendf(&op->esil, "%s,%s,>>,%s,=", - R_REG(rs) ? R_REG(rs) : R_REG(sa), R_REG(rt), R_REG(rd)); - break; - case MIPS_INS_SLLV: - case MIPS_INS_SLL: - rz_strbuf_appendf(&op->esil, "%s,%s,<<,%s,=", - R_REG(rs) ? R_REG(rs) : R_REG(sa), R_REG(rt), R_REG(rd)); - break; - case MIPS_INS_BAL: - case MIPS_INS_JAL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), I_REG(jump)); - break; - case MIPS_INS_JALR: - case MIPS_INS_JALRS: - if (strcmp(R_REG(rd), "rd") == 0) { - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), R_REG(rs)); - } else { - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_DR("%s", "%s"), R_REG(rd), R_REG(rs)); - } - break; - case MIPS_INS_JR: - case MIPS_INS_JRC: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_J("%s"), R_REG(rs)); - break; - case MIPS_INS_J: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_J("%s"), J_REG(jump)); - break; - case MIPS_INS_B: - // jump to address with conditional - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_J("%s"), I_REG(jump)); - break; - case MIPS_INS_BNE: // bne $s, $t, offset - case MIPS_INS_BNEL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,!,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(rt), I_REG(jump)); - break; - case MIPS_INS_BEQ: - case MIPS_INS_BEQL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(rt), I_REG(jump)); - break; - case MIPS_INS_BZ: - case MIPS_INS_BEQZ: - case MIPS_INS_BEQZC: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BNEZ: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,!,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BLEZ: - case MIPS_INS_BLEZC: - case MIPS_INS_BLEZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{," ES_J("%s") ",BREAK,},", - I_REG(rs), I_REG(jump)); - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BGEZ: - case MIPS_INS_BGEZC: - case MIPS_INS_BGEZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BGEZAL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BLTZAL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BLTZ: - case MIPS_INS_BLTZC: - case MIPS_INS_BLTZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BGTZ: - case MIPS_INS_BGTZC: - case MIPS_INS_BGTZL: - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{,BREAK,},", I_REG(rs)); - rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}", - I_REG(rs), I_REG(jump)); - break; - case MIPS_INS_BTEQZ: - break; - case MIPS_INS_BTNEZ: - break; - case MIPS_INS_MOV: - case MIPS_INS_MOVE: - rz_strbuf_appendf(&op->esil, "%s,%s,=", R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_MOVZ: - case MIPS_INS_MOVF: - rz_strbuf_appendf(&op->esil, "0,%s,==,$z,?{,%s,%s,=,}", - R_REG(rt), R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_MOVT: - rz_strbuf_appendf(&op->esil, "1,%s,==,$z,?{,%s,%s,=,}", - R_REG(rt), R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_FSUB: - case MIPS_INS_SUB: - case MIPS_INS_SUBU: - case MIPS_INS_DSUB: - case MIPS_INS_DSUBU: - rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", - R_REG(rt), R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_NEG: - case MIPS_INS_NEGU: - break; - /** signed -- sets overflow flag */ - case MIPS_INS_ADD: - ES_ADD_CK32_OVERF(R_REG(rs), R_REG(rt), R_REG(rd)); - break; - case MIPS_INS_ADDI: - ES_ADD_CK32_OVERF(I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_DADD: - ES_ADD_CK64_OVERF(R_REG(rs), R_REG(rt), R_REG(rd)); - break; - case MIPS_INS_DADDU: - case MIPS_INS_ADDU: - rz_strbuf_appendf(&op->esil, "%s,%s,+,%s,=", - R_REG(rt), R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_DADDI: - ES_ADD_CK64_OVERF(I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_ADDIU: - case MIPS_INS_DADDIU: - rz_strbuf_appendf(&op->esil, "%s,%s,+,%s,=", - I_REG(imm), I_REG(rs), I_REG(rt)); - ES_SIGN32_64(I_REG(rt)); - break; - case MIPS_INS_LI: - case MIPS_INS_LDI: - rz_strbuf_appendf(&op->esil, "%s,%s,=", I_REG(imm), I_REG(rt)); - break; - case MIPS_INS_LUI: - rz_strbuf_appendf(&op->esil, "%s0000,%s,=", I_REG(imm), I_REG(rt)); - break; - case MIPS_INS_LB: - op->sign = true; // To load a byte from memory as a signed value - /* fallthrough */ - case MIPS_INS_LBU: - // one of these is wrong - rz_strbuf_appendf(&op->esil, "%s,%s,+,[1],%s,=", - I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_LW: - case MIPS_INS_LWC1: - case MIPS_INS_LWC2: - case MIPS_INS_LWL: - case MIPS_INS_LWR: - case MIPS_INS_LWU: - case MIPS_INS_LL: - rz_strbuf_appendf(&op->esil, "%s,%s,+,[4],%s,=", - I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_LDL: - case MIPS_INS_LDC1: - case MIPS_INS_LDC2: - case MIPS_INS_LLD: - case MIPS_INS_LD: - rz_strbuf_appendf(&op->esil, "%s,%s,+,[8],%s,=", - I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_LH: - op->sign = true; // To load a byte from memory as a signed value - /* fallthrough */ - case MIPS_INS_LHU: - rz_strbuf_appendf(&op->esil, "%s,%s,+,[2],%s,=", - I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_LHX: - case MIPS_INS_LWX: - break; - case MIPS_INS_AND: - rz_strbuf_appendf(&op->esil, "%s,%s,&,%s,=", R_REG(rt), R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_ANDI: - rz_strbuf_appendf(&op->esil, "%s,%s,&,%s,=", I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_OR: - rz_strbuf_appendf(&op->esil, "%s,%s,|,%s,=", R_REG(rt), R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_ORI: - rz_strbuf_appendf(&op->esil, "%s,%s,|,%s,=", I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_XOR: - rz_strbuf_appendf(&op->esil, "%s,%s,^,%s,=", R_REG(rt), R_REG(rs), R_REG(rd)); - break; - case MIPS_INS_XORI: - rz_strbuf_appendf(&op->esil, "%s,%s,^,%s,=", I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_NOR: - rz_strbuf_appendf(&op->esil, "%s,%s,|,0xffffffff,^,%s,=", R_REG(rs), R_REG(rt), R_REG(rd)); - break; - case MIPS_INS_SLT: - rz_strbuf_appendf(&op->esil, "%s,%s,<,t,=", R_REG(rs), R_REG(rt)); - break; - case MIPS_INS_SLTI: - rz_strbuf_appendf(&op->esil, "%s,%s,<,%s,=", I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_SLTU: - rz_strbuf_appendf(&op->esil, "%s,0xffffffff,&,%s,0xffffffff,&,<,t,=", - R_REG(rs), R_REG(rt)); - break; - case MIPS_INS_SLTIU: - rz_strbuf_appendf(&op->esil, "%s,0xffffffff,&,%s,0xffffffff,&,<,%s,=", - I_REG(imm), I_REG(rs), I_REG(rt)); - break; - case MIPS_INS_MUL: - rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",%s,=", R_REG(rs), R_REG(rt), R_REG(rd)); - ES_SIGN32_64(R_REG(rd)); - break; - case MIPS_INS_MULT: - case MIPS_INS_MULTU: - rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",lo,=", R_REG(rs), R_REG(rt)); - ES_SIGN32_64("lo"); - rz_strbuf_appendf(&op->esil, ES_W("32,%s,%s,*,>>") ",hi,=", R_REG(rs), R_REG(rt)); - ES_SIGN32_64("hi"); - break; - case MIPS_INS_MFLO: - rz_strbuf_appendf(&op->esil, "lo,%s,=", R_REG(rd)); - break; - case MIPS_INS_MFHI: - rz_strbuf_appendf(&op->esil, "hi,%s,=", R_REG(rd)); - break; - case MIPS_INS_MTLO: - rz_strbuf_appendf(&op->esil, "%s,lo,=,", R_REG(rs)); - ES_SIGN32_64("lo"); - break; - case MIPS_INS_MTHI: - rz_strbuf_appendf(&op->esil, "%s,hi,=,", R_REG(rs)); - ES_SIGN32_64("hi"); - break; - default: - return -1; - } - - return 0; -} - -static int mips_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) { - ut8 opcode[4] = { 0 }; - int optype = 0, oplen = (analysis->bits == 16) ? 2 : 4; - gnu_insn insn = { 0 }; - - if (!op || len < 4) { - return oplen; - } - - op->type = RZ_ANALYSIS_OP_TYPE_UNK; - op->size = oplen; - op->addr = addr; - - if (!buf[0] && !buf[1] && !buf[2] && !buf[3]) { - op->type = RZ_ANALYSIS_OP_TYPE_NOP; - return oplen; - } - - if (analysis->big_endian) { - memcpy(opcode, buf, oplen); - } else { - opcode[0] = buf[3]; - opcode[1] = buf[2]; - opcode[2] = buf[1]; - opcode[3] = buf[0]; - } - - optype = opcode[0] >> 2; - insn.optype = optype; - insn.id = 0; - - if (optype == 0) { - /* - R-TYPE - ====== - opcode (6) rs (5) rt (5) rd (5) sa (5) function (6) - rs = register source - rt = register target - rd = register destination - sa = - fu = - |--[0]--| |--[1]--| |--[2]--| |--[3]--| - 1111 1111 1111 1111 1111 1111 1111 1111 - \_op__/\_rs__/\_rt_/ \_rd_/\_sa__/\_fun_/ - | | | | | | - buf[0]>>2 | (buf[1]&31) | | buf[3]&63 - | (buf[2]>>3) | - (buf[0]&3)<<3)+(buf[1]>>5) (buf[2]&7)+(buf[3]>>6) -*/ - int rs = ((opcode[0] & 3) << 3) + (opcode[1] >> 5); - int rt = opcode[1] & 31; - int rd = opcode[2] >> 3; - int sa = ((opcode[2] & 7) << 2) + (opcode[3] >> 6); - int fun = opcode[3] & 63; - - insn.r_reg.rs = mips_reg_decode(rs); - insn.r_reg.rd = mips_reg_decode(rd); - insn.r_reg.rt = mips_reg_decode(rt); - snprintf((char *)insn.r_reg.sa, REG_BUF_MAX, "%" PFMT32d, sa); - - switch (fun) { - case 0: // sll - insn.id = MIPS_INS_SLL; - insn.r_reg.rs = NULL; - op->val = sa; - // fallthrough - case 4: // sllv - insn.id = MIPS_INS_SLLV; - op->type = RZ_ANALYSIS_OP_TYPE_SHL; - break; - case 2: // srl - insn.id = MIPS_INS_SRL; - insn.r_reg.rs = NULL; - op->val = sa; - // fallthrough - case 6: // srlv - insn.id = MIPS_INS_SRLV; - op->type = RZ_ANALYSIS_OP_TYPE_SHR; - break; - case 3: // sra - insn.id = MIPS_INS_SRA; - op->type = RZ_ANALYSIS_OP_TYPE_SAR; - break; - case 7: // srav - insn.id = MIPS_INS_SRAV; - op->type = RZ_ANALYSIS_OP_TYPE_SAR; - break; - case 59: // dsra - insn.id = MIPS_INS_DSRA; // TODO double - op->type = RZ_ANALYSIS_OP_TYPE_SAR; - break; - case 63: // dsra32 - insn.id = MIPS_INS_DSRA32; - op->type = RZ_ANALYSIS_OP_TYPE_SAR; - break; - case 8: // jr - // RZ_LOG_DEBUG("%" PFMT64x " jr\n", addr); - // TODO: check return value - op->delay = 1; - insn.id = MIPS_INS_JR; - if (rs == 31) { - op->type = RZ_ANALYSIS_OP_TYPE_RET; - } else if (rs == 25) { - op->type = RZ_ANALYSIS_OP_TYPE_RJMP; - op->jump = t9_pre; - break; - } else { - op->type = RZ_ANALYSIS_OP_TYPE_RJMP; - } - break; - case 9: // jalr - // RZ_LOG_DEBUG("%" PFMT64x " jalr\n", addr); - op->delay = 1; - insn.id = MIPS_INS_JALR; - if (rs == 25) { - op->type = RZ_ANALYSIS_OP_TYPE_RCALL; - op->jump = t9_pre; - break; - } - op->type = RZ_ANALYSIS_OP_TYPE_UCALL; - break; - case 10: // movz - insn.id = MIPS_INS_MOVZ; - break; - case 12: // syscall - op->type = RZ_ANALYSIS_OP_TYPE_SWI; - break; - case 13: // break - op->type = RZ_ANALYSIS_OP_TYPE_TRAP; - break; - case 16: // mfhi - insn.id = MIPS_INS_MFHI; - break; - case 18: // mflo - insn.id = MIPS_INS_MFLO; - break; - case 17: // mthi - insn.id = MIPS_INS_MTHI; - break; - case 19: // mtlo - insn.id = MIPS_INS_MTLO; - op->type = RZ_ANALYSIS_OP_TYPE_MOV; - break; - case 24: // mult - insn.id = MIPS_INS_MULT; - // fallthrough - case 25: // multu - insn.id = MIPS_INS_MULTU; - op->type = RZ_ANALYSIS_OP_TYPE_MUL; - break; - case 26: // div - case 27: // divu - op->type = RZ_ANALYSIS_OP_TYPE_DIV; - insn.id = MIPS_INS_DIV; - break; - case 32: // add - insn.id = MIPS_INS_ADD; - // fallthrough - case 33: // addu //TODO:表明位数 - insn.id = MIPS_INS_ADDU; - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - break; - case 44: // dadd - insn.id = MIPS_INS_DADD; - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - break; - case 45: // daddu move - if (rt == 0) { - op->type = RZ_ANALYSIS_OP_TYPE_MOV; - insn.id = MIPS_INS_MOV; - break; - } - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - insn.id = MIPS_INS_DADDU; - break; - case 34: // sub - case 35: // subu - insn.id = MIPS_INS_SUB; - op->type = RZ_ANALYSIS_OP_TYPE_SUB; - break; - case 46: // dsub - insn.id = MIPS_INS_SUB; - op->type = RZ_ANALYSIS_OP_TYPE_SUB; - break; - case 47: // dsubu - insn.id = MIPS_INS_SUB; - op->type = RZ_ANALYSIS_OP_TYPE_SUB; - break; - case 36: // and - insn.id = MIPS_INS_AND; - op->type = RZ_ANALYSIS_OP_TYPE_AND; - break; - case 37: // or - insn.id = MIPS_INS_OR; - op->type = RZ_ANALYSIS_OP_TYPE_OR; - break; - case 38: // xor - insn.id = MIPS_INS_XOR; - op->type = RZ_ANALYSIS_OP_TYPE_XOR; - break; - case 39: // nor - insn.id = MIPS_INS_NOR; - op->type = RZ_ANALYSIS_OP_TYPE_NOR; - break; - case 42: // slt - insn.id = MIPS_INS_SLT; - break; - case 43: // sltu - insn.id = MIPS_INS_SLTU; - break; - default: - // RZ_LOG_DEBUG("%" PFMT64x " %d\n", addr, optype); - break; - } - // family = 'R'; - } else if ((optype & 0x3e) == 2) { - /* - // J-TYPE - |--[0]--| |--[1]--| |--[2]--| |--[3]--| - 1111 1111 1111 1111 1111 1111 1111 1111 - \_op__/\______address____________________/ - | | - (buf[0]>>2) ((buf[0]&3)<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3] -*/ - // FIXME: what happens when addr is using a virtual map? - // ANS: address will be E 0x000000..0x0ffffffc - // but addr could be anywhere - // so address needs to be adjusted for that, somehow... - // MIPS is strange. For example, the same code memory may be - // mapped simultaneously to 0x00600000 and 0x80600000. The program is - // executing at 0x80600000 if we are operating in 'KSEG0' space - // (unmapped cached mode) vs 0x00600000 (KUSEG or user space) - // An immediate jump can only reach within 2^28 bits. - // HACK: if the user specified a mapping for the program - // then assume that they know which MIPS segment they - // are analysing in, and use the high order bits of addr - // to be add to the jump. - // WARNING: it is possible that this may not be the case - // in all situations! - // Maybe better solution: use a cfg. variable to do - // the offset... but I dont yet know how to get to that - // from this static function - int address = (((opcode[0] & 3) << 24) + (opcode[1] << 16) + (opcode[2] << 8) + opcode[3]) << 2; - ut64 page_hack = addr & 0xf0000000; - - switch (optype) { - case 2: // j - insn.id = MIPS_INS_J; - op->type = RZ_ANALYSIS_OP_TYPE_JMP; - op->jump = page_hack + address; - op->delay = 1; - snprintf((char *)insn.j_reg.jump, REG_BUF_MAX, "0x%" PFMT64x, op->jump); - break; - case 3: // jal - insn.id = MIPS_INS_JAL; - op->type = RZ_ANALYSIS_OP_TYPE_CALL; - op->jump = page_hack + address; - op->fail = addr + 8; - op->delay = 1; - snprintf((char *)insn.j_reg.jump, REG_BUF_MAX, "0x%" PFMT64x, op->jump); - break; - } - // family = 'J'; - } else if ((optype & 0x3c) == 0x10) { -/* - C-TYPE - ====== - opcode (6) format (5) ft (5) fs (5) fd (5) function (6) - - |--[0]--| |--[1]--| |--[2]--| |--[3]--| - 1111 1111 1111 1111 1111 1111 1111 1111 - \_op__/\_fmt_/\_ft_/ \_fs_/\_fd__/\_fun_/ - | | | | | | - buf[0]>>2 | (buf[1]&31) | | buf[3]&63 - | (buf[2]>>3) | - (buf[0]&3)<<3)+(buf[1]>>5) (buf[2]&7)+(buf[3]>>6) -*/ -#if WIP - int fmt = ((opcode[0] & 3) << 3) + (opcode[1] >> 5); - int ft = (opcode[1] & 31); - int fs = (opcode[2] >> 3); - int fd = (opcode[2] & 7) + (opcode[3] >> 6); -#endif - int fun = (opcode[3] & 63); - // family = 'C'; - switch (fun) { - case 0: // mtc1 - break; - case 1: // sub.s - break; - case 2: // mul.s - break; - case 3: // div.s - break; - // .... - } - } else { - /* - I-TYPE - ====== - all opcodes but 000000 000001x and 0100xx - opcode (6) rs (5) rt (5) immediate (16) - - |--[0]--| |--[1]--| |--[2]--| |--[3]--| - 1111 1111 1111 1111 1111 1111 1111 1111 - \_op__/\_rs__/\_rt_/ \_______imm________/ - | | | | - buf[0]>>2 | (buf[1]&31) | - | | - ((buf[0]&3)<<3)+(buf[1]>>5) (buf[2]<<8)+buf[3] -*/ - op->refptr = 0; - int rs = ((opcode[0] & 3) << 3) + (opcode[1] >> 5); - int rt = opcode[1] & 31; - int imm = (opcode[2] << 8) + opcode[3]; - if (((optype >> 2) ^ 0x3) && (imm & 0x8000)) { - imm = 0 - (0x10000 - imm); - } - - insn.i_reg.rs = mips_reg_decode(rs); - insn.i_reg.rt = mips_reg_decode(rt); - snprintf((char *)insn.i_reg.imm, REG_BUF_MAX, "%" PFMT32d, imm); - - switch (optype) { - case 1: - switch (rt) { - case 0: // bltz - insn.id = MIPS_INS_BLTZ; - break; - case 1: // bgez - insn.id = MIPS_INS_BGEZ; - break; - case 17: // bal bgezal - if (rs == 0) { - op->jump = addr + (imm << 2) + 4; - snprintf((char *)insn.i_reg.jump, REG_BUF_MAX, "0x%" PFMT64x, op->jump); - insn.id = MIPS_INS_BAL; - } else { - op->fail = addr + 8; - insn.id = MIPS_INS_BGEZAL; - } - op->delay = 1; - op->type = RZ_ANALYSIS_OP_TYPE_CALL; - break; - default: - op->delay = 1; - op->fail = addr + 8; - break; - } - break; - case 4: // beq - if (!insn.id) { - insn.id = MIPS_INS_BEQ; - if (rt == 0) { - insn.id = MIPS_INS_BEQZ; - } - } - // fallthrough - case 5: // bne // also bnez - if (!insn.id) { - insn.id = MIPS_INS_BNE; - if (rt == 0) { - insn.id = MIPS_INS_BNEZ; - } - } - // fallthrough - case 6: // blez - if (!insn.id) { - insn.id = MIPS_INS_BLEZ; - } - // fallthrough - case 7: // bgtz - // XXX: use imm here - if (!insn.id) { - insn.id = MIPS_INS_BGTZ; - } - op->type = RZ_ANALYSIS_OP_TYPE_CJMP; - op->jump = addr + (imm << 2) + 4; - op->fail = addr + 8; - op->delay = 1; - - snprintf((char *)insn.i_reg.jump, REG_BUF_MAX, "0x%" PFMT64x, op->jump); - break; - // The following idiom is very common in mips 32 bit: - // - // lui a0,0x8123 - // ; maybe other opcodes - // ; maybe even a jump with branch delay - // addui a0,a0,-12345 - // - // Here, a0 might typically be any a0 or s0 register, and -12345 is a signed 16-bit number - // This is used to address const or static data in a 64kb page - // 0x8123 is the upper 16 bits of the register - // The net result: a0 := 0x8122cfc7 - // The cases vary, so for now leave the smarts in a human generated macro to decide - // but the macro needs the opcode values as input - // - // TODO: this is a stop-gap. Really we need some smarts in here to tie this into the - // flags directly, as suggested here: https://github.com/rizinorg/rizin/issues/949#issuecomment-43654922 - case 15: // lui - insn.id = MIPS_INS_LUI; - snprintf((char *)insn.i_reg.imm, REG_BUF_MAX, "0x%" PFMT32x, imm); - op->dst = rz_analysis_value_new(); - op->dst->reg = rz_reg_get(analysis->reg, mips_reg_decode(rt), RZ_REG_TYPE_GPR); - // TODO: currently there is no way for the macro to get access to this register - op->val = imm; - break; - case 9: // addiu - insn.id = MIPS_INS_ADDIU; - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - op->dst = rz_analysis_value_new(); - op->dst->reg = rz_reg_get(analysis->reg, mips_reg_decode(rt), RZ_REG_TYPE_GPR); - // TODO: currently there is no way for the macro to get access to this register - op->src[0] = rz_analysis_value_new(); - op->src[0]->reg = rz_reg_get(analysis->reg, mips_reg_decode(rs), RZ_REG_TYPE_GPR); - op->val = imm; // Beware: this one is signed... use `%vi $v` - if (rs == 0) { - insn.id = MIPS_INS_LI; - snprintf((char *)insn.i_reg.imm, REG_BUF_MAX, "0x%" PFMT32x, imm); - } - break; - case 8: // addi - insn.id = MIPS_INS_ADDI; - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - break; - case 10: // slti - insn.id = MIPS_INS_SLTI; - break; - case 11: // sltiu - insn.id = MIPS_INS_SLTIU; - break; - case 12: // andi - insn.id = MIPS_INS_ANDI; - op->type = RZ_ANALYSIS_OP_TYPE_AND; - break; - case 13: // ori - insn.id = MIPS_INS_ORI; - op->type = RZ_ANALYSIS_OP_TYPE_OR; - break; - case 14: // xori - insn.id = MIPS_INS_XORI; - op->type = RZ_ANALYSIS_OP_TYPE_XOR; - break; - case 24: // daddi - insn.id = MIPS_INS_DADDI; - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - break; - case 25: // daddiu - insn.id = MIPS_INS_DADDIU; - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - if (rs == 0) { - insn.id = MIPS_INS_LDI; - snprintf((char *)insn.i_reg.imm, REG_BUF_MAX, "0x%" PFMT32x, imm); - } - break; - case 32: // lb - op->refptr = 1; - insn.id = MIPS_INS_LB; - /* fallthrough */ - case 33: // lh - if (!op->refptr) { - op->refptr = 2; - insn.id = MIPS_INS_LB; - } - /* fallthrough */ - case 35: // lw - if (!op->refptr) { - op->refptr = 4; - insn.id = MIPS_INS_LW; - } - /* fallthrough */ - case 55: // ld - if (!op->refptr) { - op->refptr = 8; - insn.id = MIPS_INS_LD; - } - - if (rs == 28) { - op->ptr = analysis->gp + imm; - } else { - op->ptr = imm; - } - if (rt == 25) { - t9_pre = op->ptr; - } - op->type = RZ_ANALYSIS_OP_TYPE_LOAD; - break; - case 36: // lbu - insn.id = MIPS_INS_LBU; - op->type = RZ_ANALYSIS_OP_TYPE_LOAD; - break; - case 37: // lhu - insn.id = MIPS_INS_LHU; - op->type = RZ_ANALYSIS_OP_TYPE_LOAD; - break; - case 40: // sb - insn.id = MIPS_INS_SB; - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - break; - case 41: // sh - insn.id = MIPS_INS_SH; - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - break; - case 43: // sw - insn.id = MIPS_INS_SW; - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - break; - case 63: // sd - insn.id = MIPS_INS_SD; - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - break; - case 49: // lwc1 - case 57: // swc1 - break; - case 29: // jalx - insn.id = MIPS_INS_JALX; - op->type = RZ_ANALYSIS_OP_TYPE_CALL; - op->jump = addr + 4 * ((opcode[3] | opcode[2] << 8 | opcode[1] << 16)); - op->fail = addr + 8; - op->delay = 1; - snprintf((char *)insn.i_reg.jump, REG_BUF_MAX, "0x%" PFMT64x, op->jump); - - break; - } - // family = 'I'; - } - - if (mask & RZ_ANALYSIS_OP_MASK_ESIL) { - if (analyze_op_esil(analysis, op, addr, &insn)) { - rz_strbuf_fini(&op->esil); - } - } - if (mask & RZ_ANALYSIS_OP_MASK_VAL) { - // TODO: add op_fillval (analysis, op, &insn); - } - return oplen; -} - -/* - R - all instructions that only take registers as arguments (jalr, jr) - opcode 000000 - opcode (6) rs (5) rt (5) rd (5) sa (5) function (6) - add rd, rs, rt 100000 - addu rd, rs, rt 100001 - and rd, rs, rt 100100 - break 001101 - div rs, rt 011010 - divu rs, rt 011011 - jalr rd, rs 001001 - jr rs 001000 - - mfhi rd 010000 - mflo rd 010010 - mthi rs 010001 - mtlo rs 010011 - mult rs, rt 011000 - multu rs, rt 011001 - - nor rd, rs, rt 100111 - or rd, rs, rt 100101 - sll rd, rt, sa 000000 - sllv rd, rt, rs 000100 - slt rd, rs, rt 101010 - sltu rd, rs, rt 101011 - - sra rd, rt, sa 000011 - srav rd, rt, rs 000111 - - srl rd, rt, sa 000010 - srlv rd, rt, rs 000110 - - sub rd, rs, rt 100010 - subu rd, rs, rt 100011 - syscall 001100 - xor rd, rs, rt 100110 - I - instructions with immediate operand, load/store/.. - all opcodes but 000000 000001x and 0100xx - opcode (6) rs (5) rt (5) immediate (16) - addi rt, rs, immediate 001000 - addiu rt, rs, immediate 001001 - andi rt, rs, immediate 001100 - beq rs, rt, label 000100 - - bgez rs, label 000001 rt = 00001 - - bgtz rs, label 000111 rt = 00000 - blez rs, label 000110 rt = 00000 - - bltz rs, label 000001 rt = 00000 - bne rs, rt, label 000101 - lb rt, immediate(rs) 100000 - lbu rt, immediate(rs) 100100 - - lh rt, immediate(rs) 100001 - lhu rt, immediate(rs) 100101 - - lui rt, immediate 001111 - - lw rt, immediate(rs) 100011 - lwc1 rt, immediate(rs) 110001 - - ori rt, rs, immediate 001101 - sb rt, immediate(rs) 101000 - - slti rt, rs, immediate 001010 - sltiu rt, rs, immediate 001011 - sh rt, immediate(rs) 101001 - sw rt, immediate(rs) 101011 - swc1 rt, immediate(rs) 111001 - xori rt, rs, immediate 001110 - J - require memory address like j, jal - 00001x - opcode (6) target (26) - j label 000010 coded address of label - jal label 000011 coded address of label - C - coprocessor insutrctions that use cp0, cp1, .. - 0100xx - opcode (6) format (5) ft (5) fs (5) fd (5) function (6) - add.s fd, fs, ft 000000 10000 - cvt.s.w fd, fs, ft 100000 10100 - cvt.w.s fd, fs, ft 100100 10000 - div.s fd, fs, ft 000011 10000 - mfc1 ft, fs 000000 00000 - mov.s fd, fs 000110 10000 - mtc1 ft, fs 000000 00100 - mul.s fd, fs, ft 000010 10000 - sub.s fd, fs, ft 000001 10000 -*/ - -/* Set the profile register */ -static char *mips_get_reg_profile(RzAnalysis *analysis) { - const char *p = -#if 0 - "=PC pc\n" - "=SP sp\n" - "=A0 a0\n" - "=A1 a1\n" - "=A2 a2\n" - "=A3 a3\n" - "gpr zero .32 0 0\n" - "gpr at .32 4 0\n" - "gpr v0 .32 8 0\n" - "gpr v1 .32 12 0\n" - "gpr a0 .32 16 0\n" - "gpr a1 .32 20 0\n" - "gpr a2 .32 24 0\n" - "gpr a3 .32 28 0\n" - "gpr t0 .32 32 0\n" - "gpr t1 .32 36 0\n" - "gpr t2 .32 40 0\n" - "gpr t3 .32 44 0\n" - "gpr t4 .32 48 0\n" - "gpr t5 .32 52 0\n" - "gpr t6 .32 56 0\n" - "gpr t7 .32 60 0\n" - "gpr s0 .32 64 0\n" - "gpr s1 .32 68 0\n" - "gpr s2 .32 72 0\n" - "gpr s3 .32 76 0\n" - "gpr s4 .32 80 0\n" - "gpr s5 .32 84 0\n" - "gpr s6 .32 88 0\n" - "gpr s7 .32 92 0\n" - "gpr t8 .32 96 0\n" - "gpr t9 .32 100 0\n" - "gpr k0 .32 104 0\n" - "gpr k1 .32 108 0\n" - "gpr gp .32 112 0\n" - "gpr sp .32 116 0\n" - "gpr fp .32 120 0\n" - "gpr ra .32 124 0\n" - "gpr pc .32 128 0\n"; -#else - // take the one from the debugger // - "=PC pc\n" - "=SP sp\n" - "=BP fp\n" - "=A0 a0\n" - "=A1 a1\n" - "=A2 a2\n" - "=A3 a3\n" - "gpr zero .64 0 0\n" - // XXX DUPPED CAUSES FAILURE "gpr at .32 8 0\n" - "gpr at .64 8 0\n" - "gpr v0 .64 16 0\n" - "gpr v1 .64 24 0\n" - /* args */ - "gpr a0 .64 32 0\n" - "gpr a1 .64 40 0\n" - "gpr a2 .64 48 0\n" - "gpr a3 .64 56 0\n" - /* tmp */ - "gpr t0 .64 64 0\n" - "gpr t1 .64 72 0\n" - "gpr t2 .64 80 0\n" - "gpr t3 .64 88 0\n" - "gpr t4 .64 96 0\n" - "gpr t5 .64 104 0\n" - "gpr t6 .64 112 0\n" - "gpr t7 .64 120 0\n" - /* saved */ - "gpr s0 .64 128 0\n" - "gpr s1 .64 136 0\n" - "gpr s2 .64 144 0\n" - "gpr s3 .64 152 0\n" - "gpr s4 .64 160 0\n" - "gpr s5 .64 168 0\n" - "gpr s6 .64 176 0\n" - "gpr s7 .64 184 0\n" - "gpr t8 .64 192 0\n" - "gpr t9 .64 200 0\n" - /* special */ - "gpr k0 .64 208 0\n" - "gpr k1 .64 216 0\n" - "gpr gp .64 224 0\n" - "gpr sp .64 232 0\n" - "gpr fp .64 240 0\n" - "gpr ra .64 248 0\n" - /* extra */ - "gpr pc .64 272 0\n"; -#endif - return rz_str_dup(p); -} - -static int archinfo(RzAnalysis *a, RzAnalysisInfoType query) { - switch (query) { - case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE: - /* fall-thru */ - case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE: - /* fall-thru */ - case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN: - /* fall-thru */ - case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN: - return 4; - case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS: - return true; - default: - return -1; - } -} - -RzAnalysisPlugin rz_analysis_plugin_mips_gnu = { - .name = "mips.gnu", - .desc = "MIPS code analysis plugin", - .license = "LGPL3", - .arch = "mips", - .bits = 32, - .esil = true, - .archinfo = archinfo, - .op = &mips_op, - .get_reg_profile = mips_get_reg_profile, -}; diff --git a/librz/arch/p_gnu/arch_mips.c b/librz/arch/p_gnu/arch_mips.c deleted file mode 100644 index b599554a903..00000000000 --- a/librz/arch/p_gnu/arch_mips.c +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2024 RizinOrg -// SPDX-FileCopyrightText: 2024 deroad -// SPDX-License-Identifier: LGPL-3.0-only - -#include - -#include "analysis/analysis_mips_gnu.c" -#include "asm/asm_mips_gnu.c" - -RZ_ARCH_PLUGIN_DEFINE_DEPRECATED(mips_gnu); diff --git a/librz/arch/p_gnu/asm/asm_mips_gnu.c b/librz/arch/p_gnu/asm/asm_mips_gnu.c deleted file mode 100644 index 86c24ada6d1..00000000000 --- a/librz/arch/p_gnu/asm/asm_mips_gnu.c +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-FileCopyrightText: 2009-2018 pancake -// SPDX-FileCopyrightText: 2009-2018 nibble -// SPDX-License-Identifier: LGPL-3.0-only - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include - -static int mips_mode = 0; -static unsigned long Offset = 0; -static RzStrBuf *buf_global = NULL; -static unsigned char bytes[4]; -static char *pre_cpu = NULL; -static char *pre_features = NULL; - -static int mips_buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info) { - int delta = (memaddr - Offset); - if (delta < 0) { - return -1; // disable backward reads - } - if ((delta + length) > 4) { - return -1; - } - memcpy(myaddr, bytes + delta, length); - return 0; -} - -static int symbol_at_address(bfd_vma addr, struct disassemble_info *info) { - return 0; -} - -static void memory_error_func(int status, bfd_vma memaddr, struct disassemble_info *info) { - //-- -} - -DECLARE_GENERIC_PRINT_ADDRESS_FUNC() -DECLARE_GENERIC_FPRINTF_FUNC() - -typedef struct { - struct disassemble_info disasm_obj; -} MIPSGnuContext; - -static int mips_gnu_disassemble(struct rz_asm_t *a, struct rz_asm_op_t *op, const ut8 *buf, int len) { - MIPSGnuContext *ctx = (MIPSGnuContext *)a->plugin_data; - if (len < 4) { - return -1; - } - buf_global = &op->buf_asm; - Offset = a->pc; - memcpy(bytes, buf, 4); // TODO handle thumb - - if ((a->cpu != pre_cpu) && (a->features != pre_features)) { - free(ctx->disasm_obj.disassembler_options); - memset(&ctx->disasm_obj, '\0', sizeof(struct disassemble_info)); - } - - /* prepare disassembler */ - if (a->cpu && (!pre_cpu || !strcmp(a->cpu, pre_cpu))) { - if (!rz_str_casecmp(a->cpu, "mips64r2")) { - ctx->disasm_obj.mach = bfd_mach_mipsisa64r2; - } else if (!rz_str_casecmp(a->cpu, "mips32r2")) { - ctx->disasm_obj.mach = bfd_mach_mipsisa32r2; - } else if (!rz_str_casecmp(a->cpu, "mips64")) { - ctx->disasm_obj.mach = bfd_mach_mipsisa64; - } else if (!rz_str_casecmp(a->cpu, "mips32")) { - ctx->disasm_obj.mach = bfd_mach_mipsisa32; - } - char *tmp = rz_str_dup(a->cpu); - free(pre_cpu); - pre_cpu = tmp; - } - - if (a->features && (!pre_features || !strcmp(a->features, pre_features))) { - free(ctx->disasm_obj.disassembler_options); - if (strstr(a->features, "n64")) { - ctx->disasm_obj.disassembler_options = rz_str_dup("abi=n64"); - } else if (strstr(a->features, "n32")) { - ctx->disasm_obj.disassembler_options = rz_str_dup("abi=n32"); - } else if (strstr(a->features, "o32")) { - ctx->disasm_obj.disassembler_options = rz_str_dup("abi=o32"); - } - char *tmp = rz_str_dup(a->features); - free(pre_features); - pre_features = tmp; - } - - mips_mode = a->bits; - ctx->disasm_obj.arch = CPU_LOONGSON_2F; - ctx->disasm_obj.buffer = bytes; - ctx->disasm_obj.read_memory_func = &mips_buffer_read_memory; - ctx->disasm_obj.symbol_at_address_func = &symbol_at_address; - ctx->disasm_obj.memory_error_func = &memory_error_func; - ctx->disasm_obj.print_address_func = &generic_print_address_func; - ctx->disasm_obj.buffer_vma = Offset; - ctx->disasm_obj.buffer_length = 4; - ctx->disasm_obj.endian = !a->big_endian; - ctx->disasm_obj.fprintf_func = &generic_fprintf_func; - ctx->disasm_obj.stream = stdout; - op->size = (ctx->disasm_obj.endian == BFD_ENDIAN_LITTLE) - ? print_insn_little_mips((bfd_vma)Offset, &ctx->disasm_obj) - : print_insn_big_mips((bfd_vma)Offset, &ctx->disasm_obj); - if (op->size == -1) { - rz_strbuf_set(&op->buf_asm, "(data)"); - } - return op->size; -} - -static int mips_gnu_assemble(RzAsm *a, RzAsmOp *op, const char *str) { - ut8 *opbuf = (ut8 *)rz_strbuf_get(&op->buf); - int ret = mips_assemble_opcode(str, a->pc, opbuf); - if (a->big_endian) { - ut8 tmp = opbuf[0]; - opbuf[0] = opbuf[3]; - opbuf[3] = tmp; - tmp = opbuf[1]; - opbuf[1] = opbuf[2]; - opbuf[2] = tmp; - } - return ret; -} - -static bool mips_gnu_init(void **user) { - MIPSGnuContext *ctx = RZ_NEW0(MIPSGnuContext); - rz_return_val_if_fail(ctx, false); - *user = ctx; - return true; -} - -static bool mips_gnu_fini(void *user) { - MIPSGnuContext *ctx = (MIPSGnuContext *)user; - if (ctx) { - RZ_FREE(ctx); - } - return true; -} - -RzAsmPlugin rz_asm_plugin_mips_gnu = { - .name = "mips.gnu", - .arch = "mips", - .license = "GPL3", - .bits = 32 | 64, - .endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG, - .desc = "MIPS CPU", - .init = mips_gnu_init, - .fini = mips_gnu_fini, - .disassemble = &mips_gnu_disassemble, - .assemble = &mips_gnu_assemble -}; diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index dd01264f9d0..de5c8cb112e 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -6,10 +6,6 @@ #include "elf.h" -#define EF_MIPS_ABI_O32 0x00001000 /* O32 ABI. */ -#define EF_MIPS_ABI_O64 0x00002000 /* O32 extended for 64 bit. */ -#define EF_MIPS_ABI 0x0000f000 - #define VERSYM_VERSION 0x7fff struct mips_bits_translation { @@ -47,18 +43,6 @@ struct ver_flags_translation { const char *name; }; -static const struct mips_bits_translation mips_bits_translation_table[] = { - { EF_MIPS_ARCH_1, 32 }, - { EF_MIPS_ARCH_2, 32 }, - { EF_MIPS_ARCH_3, 32 }, - { EF_MIPS_ARCH_4, 32 }, - { EF_MIPS_ARCH_5, 32 }, - { EF_MIPS_ARCH_32, 32 }, - { EF_MIPS_ARCH_64, 64 }, - { EF_MIPS_ARCH_32R2, 32 }, - { EF_MIPS_ARCH_64R2, 64 } -}; - static const struct section_note_osabi_translation section_note_osabi_translation_table[] = { { ".note.openbsd.ident", "openbsd" }, { ".note.minix.ident", "minix" }, @@ -74,7 +58,7 @@ static const struct machine_name_translation machine_name_translation_table[] = { EM_68K, "Motorola m68k family" }, { EM_88K, "Motorola m88k family" }, { EM_860, "Intel 80860" }, - { EM_MIPS, "MIPS R3000" }, + { EM_MIPS, "MIPS R3000 big-endian" }, { EM_S370, "IBM System/370" }, { EM_MIPS_RS3_LE, "MIPS R3000 little-endian" }, { EM_PARISC, "HPPA" }, @@ -230,8 +214,53 @@ static const struct class_translation class_translation_table[] = { { ELFCLASS64, "ELF64" } }; -static const struct cpu_mips_translation cpu_mips_translation_table[] = { - { EF_MIPS_ARCH_1, "mips1" }, +static const struct cpu_mips_translation gnu_mips_mach_translation_table[] = { + { EF_MIPS_MACH_3900, "3900 " }, + { EF_MIPS_MACH_4010, "4010 " }, + { EF_MIPS_MACH_4100, "4100 " }, + { EF_MIPS_MACH_ALLEGREX, "allegrex " }, + { EF_MIPS_MACH_4650, "4650 " }, + { EF_MIPS_MACH_4120, "4120 " }, + { EF_MIPS_MACH_4111, "4111 " }, + { EF_MIPS_MACH_SB1, "sb1 " }, + { EF_MIPS_MACH_OCTEON, "octeon " }, + { EF_MIPS_MACH_XLR, "xlr " }, + { EF_MIPS_MACH_OCTEON2, "octeon2 " }, + { EF_MIPS_MACH_OCTEON3, "octeon3 " }, + { EF_MIPS_MACH_5400, "5400 " }, + { EF_MIPS_MACH_5900, "5900 " }, + { EF_MIPS_MACH_IAMR2, "iamr2 " }, + { EF_MIPS_MACH_5500, "5500 " }, + { EF_MIPS_MACH_9000, "9000 " }, + { EF_MIPS_MACH_LS2E, "ls2e " }, + { EF_MIPS_MACH_LS2F, "ls2f " }, + { EF_MIPS_MACH_GS464, "gs464 " }, + { EF_MIPS_MACH_GS464E, "gs464e " }, + { EF_MIPS_MACH_GS264E, "gs264e " }, +}; + +static const struct cpu_mips_translation gnu_mips_ase_translation_table[] = { + { EF_MIPS_ARCH_ASE_MDMX, "mdmx " }, + { EF_MIPS_ARCH_ASE_M16, "mips16 " }, + { EF_MIPS_ARCH_ASE_MICROMIPS, "micromips " }, +}; + +static const struct mips_bits_translation mips_bits_translation_table[] = { + { EF_MIPS_ARCH_1, 32 }, + { EF_MIPS_ARCH_2, 32 }, + { EF_MIPS_ARCH_3, 32 }, + { EF_MIPS_ARCH_4, 32 }, + { EF_MIPS_ARCH_5, 32 }, + { EF_MIPS_ARCH_32, 32 }, + { EF_MIPS_ARCH_64, 64 }, + { EF_MIPS_ARCH_32R2, 32 }, + { EF_MIPS_ARCH_64R2, 64 }, + { EF_MIPS_ARCH_32R6, 32 }, + { EF_MIPS_ARCH_64R6, 64 }, +}; + +static const struct cpu_mips_translation gnu_mips_arch_translation_table32[] = { + { EF_MIPS_ARCH_1, "mips5" }, // also used for generic mips, so we default to mips5 { EF_MIPS_ARCH_2, "mips2" }, { EF_MIPS_ARCH_3, "mips3" }, { EF_MIPS_ARCH_4, "mips4" }, @@ -240,6 +269,22 @@ static const struct cpu_mips_translation cpu_mips_translation_table[] = { { EF_MIPS_ARCH_64, "mips64" }, { EF_MIPS_ARCH_32R2, "mips32r2" }, { EF_MIPS_ARCH_64R2, "mips64r2" }, + { EF_MIPS_ARCH_32R6, "mips32r6" }, + { EF_MIPS_ARCH_64R6, "mips64r6" }, +}; + +static const struct cpu_mips_translation gnu_mips_arch_translation_table64[] = { + { EF_MIPS_ARCH_1, "mips64" }, // also used for generic mips, so we default to mips64 + { EF_MIPS_ARCH_2, "mips64r2" }, + { EF_MIPS_ARCH_3, "mips64r3" }, + { EF_MIPS_ARCH_4, "mips64r5" }, + { EF_MIPS_ARCH_5, "mips64r6" }, + { EF_MIPS_ARCH_32, "mips64" }, + { EF_MIPS_ARCH_64, "mips64" }, + { EF_MIPS_ARCH_32R2, "mips64r2" }, // should never happen but default to 64bit + { EF_MIPS_ARCH_64R2, "mips64r2" }, + { EF_MIPS_ARCH_32R6, "mips64r6" }, // should never happen but default to 64bit + { EF_MIPS_ARCH_64R6, "mips64r6" }, }; static const struct arch_translation arch_translation_table[] = { @@ -634,17 +679,20 @@ static int get_bits_mips_common(Elf_(Word) mips_type) { return 32; } -static int is_playstation_hack(ELFOBJ *bin, Elf_(Word) mips_type) { - return Elf_(rz_bin_elf_is_executable)(bin) && Elf_(rz_bin_elf_is_static)(bin) && mips_type == EF_MIPS_ARCH_3; +static inline bool is_elf_class64(ELFOBJ *bin) { + return bin->ehdr.e_ident[EI_CLASS] == ELFCLASS64; } -static int get_bits_mips(ELFOBJ *bin) { - const Elf_(Word) mips_type = bin->ehdr.e_flags & EF_MIPS_ARCH; +static inline bool is_elf_class32(ELFOBJ *bin) { + return bin->ehdr.e_ident[EI_CLASS] == ELFCLASS32; +} - if (is_playstation_hack(bin, mips_type)) { +static int get_bits_mips(ELFOBJ *bin) { + if (is_elf_class64(bin)) { return 64; } + const Elf_(Word) mips_type = bin->ehdr.e_flags & EF_MIPS_ARCH; return get_bits_mips_common(mips_type); } @@ -838,62 +886,111 @@ static char *get_file_type_basic(RZ_NONNULL ELFOBJ *bin) { static char *get_cpu_mips(ELFOBJ *bin) { Elf_(Word) mips_arch = bin->ehdr.e_flags & EF_MIPS_ARCH; + Elf_(Word) mips_ase = bin->ehdr.e_flags & EF_MIPS_ARCH_ASE; + Elf_(Word) mips_mach = bin->ehdr.e_flags & EF_MIPS_MACH; - for (size_t i = 0; i < RZ_ARRAY_SIZE(cpu_mips_translation_table); i++) { - if (mips_arch == cpu_mips_translation_table[i].arch) { - return rz_str_dup(cpu_mips_translation_table[i].name); + RzStrBuf sb; + rz_strbuf_init(&sb); + + for (size_t i = 0; i < RZ_ARRAY_SIZE(gnu_mips_mach_translation_table); i++) { + if (mips_mach == gnu_mips_mach_translation_table[i].arch) { + rz_strbuf_append(&sb, gnu_mips_mach_translation_table[i].name); + break; } } - return rz_str_dup(" Unknown mips ISA"); -} + for (size_t i = 0; i < RZ_ARRAY_SIZE(gnu_mips_ase_translation_table); i++) { + if (mips_ase == gnu_mips_ase_translation_table[i].arch) { + rz_strbuf_append(&sb, gnu_mips_ase_translation_table[i].name); + break; + } + } -static bool is_elf_class64(ELFOBJ *bin) { - return bin->ehdr.e_ident[EI_CLASS] == ELFCLASS64; + if (is_elf_class64(bin)) { + for (size_t i = 0; i < RZ_ARRAY_SIZE(gnu_mips_arch_translation_table64); i++) { + if (mips_arch == gnu_mips_arch_translation_table64[i].arch) { + rz_strbuf_append(&sb, gnu_mips_arch_translation_table64[i].name); + break; + } + } + } else { + for (size_t i = 0; i < RZ_ARRAY_SIZE(gnu_mips_arch_translation_table32); i++) { + if (mips_arch == gnu_mips_arch_translation_table32[i].arch) { + rz_strbuf_append(&sb, gnu_mips_arch_translation_table32[i].name); + break; + } + } + } + + return rz_strbuf_drain_nofree(&sb); } -static bool is_mips_o32(ELFOBJ *bin) { - if (bin->ehdr.e_ident[EI_CLASS] != ELFCLASS32) { - return false; +static char *get_abi_mips(ELFOBJ *bin) { + Elf_(Word) mips_eflags = bin->ehdr.e_flags; + Elf_(Word) mips_abi = mips_eflags & EF_MIPS_ABI; + + RzStrBuf sb; + rz_strbuf_init(&sb); + + if (mips_eflags & EF_MIPS_NOREORDER) { + rz_strbuf_append(&sb, "noreorder "); } - if ((bin->ehdr.e_flags & EF_MIPS_ABI2) != 0) { - return false; + if (mips_eflags & EF_MIPS_PIC) { + rz_strbuf_append(&sb, "pic "); } - if ((bin->ehdr.e_flags & EF_MIPS_ABI) != 0 && (bin->ehdr.e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32) { - return false; + if (mips_eflags & EF_MIPS_CPIC) { + rz_strbuf_append(&sb, "cpic "); } - return true; -} + if (mips_eflags & EF_MIPS_XGOT) { + rz_strbuf_append(&sb, "xgot "); + } -static bool is_mips_n32(ELFOBJ *bin) { - if (bin->ehdr.e_ident[EI_CLASS] != ELFCLASS32) { - return false; + if (mips_eflags & EF_MIPS_UCODE) { + rz_strbuf_append(&sb, "ucode "); } - if ((bin->ehdr.e_flags & EF_MIPS_ABI2) == 0 || (bin->ehdr.e_flags & EF_MIPS_ABI) != 0) { - return false; + if (mips_eflags & EF_MIPS_ABI2) { + rz_strbuf_append(&sb, "abi2 "); } - return true; -} + if (mips_eflags & EF_MIPS_FP64) { + rz_strbuf_append(&sb, "fp64 "); + } -static char *get_abi_mips(ELFOBJ *bin) { - if (is_elf_class64(bin)) { - return rz_str_dup("n64"); + if (mips_eflags & EF_MIPS_NAN2008) { + rz_strbuf_append(&sb, "nan2008 "); } - if (is_mips_n32(bin)) { - return rz_str_dup("n32"); + if (mips_abi == EF_MIPS_ABI_O32) { + rz_strbuf_append(&sb, "o32 "); } - if (is_mips_o32(bin)) { - return rz_str_dup("o32"); + if (mips_abi == EF_MIPS_ABI_O64) { + rz_strbuf_append(&sb, "o64 "); } - return NULL; + if (mips_abi == EF_MIPS_ABI_EABI32) { + rz_strbuf_append(&sb, "eabi32 "); + } + + if (mips_abi == EF_MIPS_ABI_EABI64) { + rz_strbuf_append(&sb, "eabi64 "); + } + + if (is_elf_class64(bin)) { + rz_strbuf_append(&sb, "n64"); + } else if (is_elf_class32(bin)) { + rz_strbuf_append(&sb, "n32"); + } + + if (rz_strbuf_is_empty(&sb)) { + return rz_str_dup("Unknown ABI"); + } + + return rz_strbuf_drain_nofree(&sb); } /** @@ -1468,10 +1565,6 @@ RZ_OWN char *Elf_(rz_bin_elf_get_arch)(RZ_NONNULL ELFOBJ *bin) { RZ_OWN char *Elf_(rz_bin_elf_get_cpu)(RZ_NONNULL ELFOBJ *bin) { rz_return_val_if_fail(bin, NULL); - if (!Elf_(rz_bin_elf_has_segments)(bin)) { - return NULL; - } - if (bin->ehdr.e_machine == EM_MIPS) { return get_cpu_mips(bin); } diff --git a/librz/bin/format/elf/glibc_elf.h b/librz/bin/format/elf/glibc_elf.h index 070db55d1ba..b4a65074a6e 100644 --- a/librz/bin/format/elf/glibc_elf.h +++ b/librz/bin/format/elf/glibc_elf.h @@ -1624,18 +1624,38 @@ typedef struct /* MIPS R3000 specific definitions. */ -/* Legal values for e_flags field of Elf32_Ehdr. */ - -#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used. */ -#define EF_MIPS_PIC 2 /* Contains PIC code. */ -#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence. */ -#define EF_MIPS_XGOT 8 -#define EF_MIPS_64BIT_WHIRL 16 -#define EF_MIPS_ABI2 32 -#define EF_MIPS_ABI_ON32 64 -#define EF_MIPS_FP64 512 /* Uses FP64 (12 callee-saved). */ -#define EF_MIPS_NAN2008 1024 /* Uses IEEE 754-2008 NaN encoding. */ -#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level. */ +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_MIPS_NOREORDER 0x00000001 /* At least one .noreorder directive appears in the source. */ +#define EF_MIPS_PIC 0x00000002 /* File contains position independent code. */ +#define EF_MIPS_CPIC 0x00000004 /* Code in file uses the standard calling sequence for calling position independent code. */ +#define EF_MIPS_XGOT 0x00000008 /* ??? Unknown flag, set in IRIX 6's BSDdup2.o in libbsd.a. */ +#define EF_MIPS_UCODE 0x00000010 /* Code in file uses UCODE (obsolete) */ +#define EF_MIPS_ABI2 0x00000020 /* Code in file uses new ABI (-n32 on Irix 6). */ +#define EF_MIPS_OPTIONS_FIRST 0x00000080 /* Process the .MIPS.options section first by ld */ +#define EF_MIPS_32BITMODE 0x00000100 /* Indicates code compiled for a 64-bit machine in 32-bit mode (regs are 32-bits wide). */ +#define EF_MIPS_FP64 0x00000200 /* 32-bit machine but FP registers are 64 bit (-mfp64). */ +#define EF_MIPS_NAN2008 0x00000400 /* Code in file uses the IEEE 754-2008 NaN encoding convention. */ +#define EF_MIPS_ARCH_ASE 0x0f000000 /* Architectural Extensions used by this file */ +#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* Use MDMX multimedia extensions */ +#define EF_MIPS_ARCH_ASE_M16 0x04000000 /* Use MIPS-16 ISA extensions */ +#define EF_MIPS_ARCH_ASE_MICROMIPS 0x02000000 /* Use MICROMIPS ISA extensions. */ +#define EF_MIPS_ARCH 0xf0000000 /* Four bit MIPS architecture field. */ +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x50000000 /* -mips32 code. */ +#define EF_MIPS_ARCH_64 0x60000000 /* -mips64 code. */ +#define EF_MIPS_ARCH_32R2 0x70000000 /* -mips32r2 code. */ +#define EF_MIPS_ARCH_64R2 0x80000000 /* -mips64r2 code. */ +#define EF_MIPS_ARCH_32R6 0x90000000 /* -mips32r6 code. */ +#define EF_MIPS_ARCH_64R6 0xa0000000 /* -mips64r6 code. */ +#define EF_MIPS_ABI 0x0000F000 /* The ABI of the file. Also see EF_MIPS_ABI2 above. */ +#define EF_MIPS_ABI_O32 0x00001000 /* The original o32 abi. */ +#define EF_MIPS_ABI_O64 0x00002000 /* O32 extended to work on 64 bit architectures */ +#define EF_MIPS_ABI_EABI32 0x00003000 /* EABI in 32 bit mode */ +#define EF_MIPS_ABI_EABI64 0x00004000 /* EABI in 64 bit mode */ /* Legal values for MIPS architecture level. */ @@ -1649,15 +1669,80 @@ typedef struct #define EF_MIPS_ARCH_32R2 0x70000000 /* MIPS32r2 code. */ #define EF_MIPS_ARCH_64R2 0x80000000 /* MIPS64r2 code. */ -/* The following are unofficial names and should not be used. */ - -#define E_MIPS_ARCH_1 EF_MIPS_ARCH_1 -#define E_MIPS_ARCH_2 EF_MIPS_ARCH_2 -#define E_MIPS_ARCH_3 EF_MIPS_ARCH_3 -#define E_MIPS_ARCH_4 EF_MIPS_ARCH_4 -#define E_MIPS_ARCH_5 EF_MIPS_ARCH_5 -#define E_MIPS_ARCH_32 EF_MIPS_ARCH_32 -#define E_MIPS_ARCH_64 EF_MIPS_ARCH_64 +/*In order to support backwards compatibility we also + define the old versions of some of these constants. */ +#define E_MIPS_ARCH_1 EF_MIPS_ARCH_1 +#define E_MIPS_ARCH_2 EF_MIPS_ARCH_2 +#define E_MIPS_ARCH_3 EF_MIPS_ARCH_3 +#define E_MIPS_ARCH_4 EF_MIPS_ARCH_4 +#define E_MIPS_ARCH_5 EF_MIPS_ARCH_5 +#define E_MIPS_ARCH_32 EF_MIPS_ARCH_32 +#define E_MIPS_ARCH_64 EF_MIPS_ARCH_64 +#define E_MIPS_ARCH_32R2 EF_MIPS_ARCH_32R2 +#define E_MIPS_ARCH_64R2 EF_MIPS_ARCH_64R2 +#define E_MIPS_ARCH_32R6 EF_MIPS_ARCH_32R6 +#define E_MIPS_ARCH_64R6 EF_MIPS_ARCH_64R6 +#define E_MIPS_ABI_O32 EF_MIPS_ABI_O32 +#define E_MIPS_ABI_O64 EF_MIPS_ABI_O64 +#define E_MIPS_ABI_EABI32 EF_MIPS_ABI_EABI32 +#define E_MIPS_ABI_EABI64 EF_MIPS_ABI_EABI64 + +/* Machine variant if we know it. This field was invented at Cygnus, + but it is hoped that other vendors will adopt it. If some standard + is developed, this code should be changed to follow it. */ +#define EF_MIPS_MACH 0x00FF0000 + +/* Cygnus is choosing values between 80 and 9F; + 00 - 7F should be left for a future standard; + the rest are open. */ + +#define EF_MIPS_MACH_3900 0x00810000 +#define EF_MIPS_MACH_4010 0x00820000 +#define EF_MIPS_MACH_4100 0x00830000 +#define EF_MIPS_MACH_ALLEGREX 0x00840000 +#define EF_MIPS_MACH_4650 0x00850000 +#define EF_MIPS_MACH_4120 0x00870000 +#define EF_MIPS_MACH_4111 0x00880000 +#define EF_MIPS_MACH_SB1 0x008a0000 +#define EF_MIPS_MACH_OCTEON 0x008b0000 +#define EF_MIPS_MACH_XLR 0x008c0000 +#define EF_MIPS_MACH_OCTEON2 0x008d0000 +#define EF_MIPS_MACH_OCTEON3 0x008e0000 +#define EF_MIPS_MACH_5400 0x00910000 +#define EF_MIPS_MACH_5900 0x00920000 +#define EF_MIPS_MACH_IAMR2 0x00930000 +#define EF_MIPS_MACH_5500 0x00980000 +#define EF_MIPS_MACH_9000 0x00990000 +#define EF_MIPS_MACH_LS2E 0x00A00000 +#define EF_MIPS_MACH_LS2F 0x00A10000 +#define EF_MIPS_MACH_GS464 0x00A20000 +#define EF_MIPS_MACH_GS464E 0x00A30000 +#define EF_MIPS_MACH_GS264E 0x00A40000 + +/* In order to support backwards compatibility we also + define the old versions of some of these constants. */ +#define E_MIPS_MACH_3900 EF_MIPS_MACH_3900 +#define E_MIPS_MACH_4010 EF_MIPS_MACH_4010 +#define E_MIPS_MACH_4100 EF_MIPS_MACH_4100 +#define E_MIPS_MACH_ALLEGREX EF_MIPS_MACH_ALLEGREX +#define E_MIPS_MACH_4650 EF_MIPS_MACH_4650 +#define E_MIPS_MACH_4120 EF_MIPS_MACH_4120 +#define E_MIPS_MACH_4111 EF_MIPS_MACH_4111 +#define E_MIPS_MACH_SB1 EF_MIPS_MACH_SB1 +#define E_MIPS_MACH_OCTEON EF_MIPS_MACH_OCTEON +#define E_MIPS_MACH_XLR EF_MIPS_MACH_XLR +#define E_MIPS_MACH_OCTEON2 EF_MIPS_MACH_OCTEON2 +#define E_MIPS_MACH_OCTEON3 EF_MIPS_MACH_OCTEON3 +#define E_MIPS_MACH_5400 EF_MIPS_MACH_5400 +#define E_MIPS_MACH_5900 EF_MIPS_MACH_5900 +#define E_MIPS_MACH_IAMR2 EF_MIPS_MACH_IAMR2 +#define E_MIPS_MACH_5500 EF_MIPS_MACH_5500 +#define E_MIPS_MACH_9000 EF_MIPS_MACH_9000 +#define E_MIPS_MACH_LS2E EF_MIPS_MACH_LS2E +#define E_MIPS_MACH_LS2F EF_MIPS_MACH_LS2F +#define E_MIPS_MACH_GS464 EF_MIPS_MACH_GS464 +#define E_MIPS_MACH_GS464E EF_MIPS_MACH_GS464E +#define E_MIPS_MACH_GS264E EF_MIPS_MACH_GS264E /* Special section indices. */ @@ -1667,21 +1752,20 @@ typedef struct #define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols. */ #define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols. */ -/* Legal values for sh_type field of Elf32_Shdr. */ - -#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link. */ -#define SHT_MIPS_MSYM 0x70000001 -#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols. */ -#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes. */ -#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ -#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging info. */ -#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information. */ +/* Processor specific section types. Legal values for sh_type field of Elf32_Shdr. */ +#define SHT_MIPS_LIBLIST 0x70000000 /* Section contains the set of dynamic shared objects used when statically linking. */ +#define SHT_MIPS_MSYM 0x70000001 /* I'm not sure what this is, but it's used on Irix 5. */ +#define SHT_MIPS_CONFLICT 0x70000002 /* Section contains list of symbols whose definitions conflict with symbols defined in shared objects. */ +#define SHT_MIPS_GPTAB 0x70000003 /* Section contains the global pointer table. */ +#define SHT_MIPS_UCODE 0x70000004 /* Section contains microcode information. The exact format is unspecified. */ +#define SHT_MIPS_DEBUG 0x70000005 /* Section contains some sort of debugging information. The exact format is unspecified. It's probably ECOFF symbols. */ +#define SHT_MIPS_REGINFO 0x70000006 /* Section contains register usage information. */ #define SHT_MIPS_PACKAGE 0x70000007 #define SHT_MIPS_PACKSYM 0x70000008 #define SHT_MIPS_RELD 0x70000009 -#define SHT_MIPS_IFACE 0x7000000b -#define SHT_MIPS_CONTENT 0x7000000c -#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +#define SHT_MIPS_IFACE 0x7000000b /* Section contains interface information. */ +#define SHT_MIPS_CONTENT 0x7000000c /* Section contains description of contents of another section. */ +#define SHT_MIPS_OPTIONS 0x7000000d /* Section contains miscellaneous options. */ #define SHT_MIPS_SHDR 0x70000010 #define SHT_MIPS_FDESC 0x70000011 #define SHT_MIPS_EXTSYM 0x70000012 @@ -1693,33 +1777,33 @@ typedef struct #define SHT_MIPS_LOCSTR 0x70000018 #define SHT_MIPS_LINE 0x70000019 #define SHT_MIPS_RFDESC 0x7000001a -#define SHT_MIPS_DELTASYM 0x7000001b -#define SHT_MIPS_DELTAINST 0x7000001c -#define SHT_MIPS_DELTACLASS 0x7000001d -#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ -#define SHT_MIPS_DELTADECL 0x7000001f -#define SHT_MIPS_SYMBOL_LIB 0x70000020 -#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#define SHT_MIPS_DELTASYM 0x7000001b /* Delta C++: symbol table */ +#define SHT_MIPS_DELTAINST 0x7000001c /* Delta C++: instance table */ +#define SHT_MIPS_DELTACLASS 0x7000001d /* Delta C++: class table */ +#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging section. */ +#define SHT_MIPS_DELTADECL 0x7000001f /* Delta C++: declarations */ +#define SHT_MIPS_SYMBOL_LIB 0x70000020 /* List of libraries the binary depends on. Includes a time stamp, version number. */ +#define SHT_MIPS_EVENTS 0x70000021 /* Events section. */ #define SHT_MIPS_TRANSLATE 0x70000022 -#define SHT_MIPS_PIXIE 0x70000023 -#define SHT_MIPS_XLATE 0x70000024 -#define SHT_MIPS_XLATE_DEBUG 0x70000025 -#define SHT_MIPS_WHIRL 0x70000026 -#define SHT_MIPS_EH_REGION 0x70000027 -#define SHT_MIPS_XLATE_OLD 0x70000028 -#define SHT_MIPS_PDR_EXCEPTION 0x70000029 -#define SHT_MIPS_XHASH 0x7000002b +#define SHT_MIPS_PIXIE 0x70000023 /* Special pixie sections */ +#define SHT_MIPS_XLATE 0x70000024 /* Address translation table (for debug info) */ +#define SHT_MIPS_XLATE_DEBUG 0x70000025 /* SGI internal address translation table (for debug info) */ +#define SHT_MIPS_WHIRL 0x70000026 /* Intermediate code */ +#define SHT_MIPS_EH_REGION 0x70000027 /* C++ exception handling region info */ +#define SHT_MIPS_XLATE_OLD 0x70000028 /* Obsolete address translation table (for debug info) */ +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 /* Runtime procedure descriptor table exception information (ucode) ??? */ +#define SHT_MIPS_ABIFLAGS 0x7000002a /* ABI related flags section. */ +#define SHT_MIPS_XHASH 0x7000002b /* GNU style symbol hash table with xlat. */ /* Legal values for sh_flags field of Elf32_Shdr. */ - -#define SHF_MIPS_GPREL 0x10000000 /* Must be in global data area. */ -#define SHF_MIPS_MERGE 0x20000000 -#define SHF_MIPS_ADDR 0x40000000 -#define SHF_MIPS_STRINGS 0x80000000 -#define SHF_MIPS_NOSTRIP 0x08000000 -#define SHF_MIPS_LOCAL 0x04000000 -#define SHF_MIPS_NAMES 0x02000000 -#define SHF_MIPS_NODUPE 0x01000000 +#define SHF_MIPS_GPREL 0x10000000 /* This section must be in the global data area. */ +#define SHF_MIPS_MERGE 0x20000000 /* This section should be merged. */ +#define SHF_MIPS_ADDR 0x40000000 /* This section contains address data of size implied by section element size. */ +#define SHF_MIPS_STRING 0x80000000 /* This section contains string data. */ +#define SHF_MIPS_NOSTRIP 0x08000000 /* This section may not be stripped. */ +#define SHF_MIPS_LOCAL 0x04000000 /* This section is local to threads. */ +#define SHF_MIPS_NAMES 0x02000000 /* Linker should generate implicit weak names for this section. */ +#define SHF_MIPS_NODUPES 0x01000000 /* Section contais text/data which may be replicated in other sections. Linker should retain only one copy. */ /* Symbol tables. */ diff --git a/librz/bin/format/te/te.c b/librz/bin/format/te/te.c index 9ff212b8edc..baaa1982504 100644 --- a/librz/bin/format/te/te.c +++ b/librz/bin/format/te/te.c @@ -214,8 +214,31 @@ ut64 rz_bin_te_get_image_base(struct rz_bin_te_obj_t *bin) { return 0LL; } +char *rz_bin_te_get_cpu(struct rz_bin_te_obj_t *bin) { + if (!bin) { + return NULL; + } + switch (bin->header->Machine) { + case TE_IMAGE_FILE_MACHINE_MIPS16: + return rz_str_dup("mips16"); + case TE_IMAGE_FILE_MACHINE_MIPSFPU: + return rz_str_dup("mips32"); + case TE_IMAGE_FILE_MACHINE_MIPSFPU16: + return rz_str_dup("mips16"); + case TE_IMAGE_FILE_MACHINE_R10000: + return rz_str_dup("r10000"); + case TE_IMAGE_FILE_MACHINE_R3000: + return rz_str_dup("r3000"); + case TE_IMAGE_FILE_MACHINE_R4000: + return rz_str_dup("r4000"); + case TE_IMAGE_FILE_MACHINE_WCEMIPSV2: + return rz_str_dup("mips2"); + default: + return NULL; + } +} + char *rz_bin_te_get_machine(struct rz_bin_te_obj_t *bin) { - char *machine; if (!bin) { return NULL; } @@ -279,7 +302,6 @@ char *rz_bin_te_get_machine(struct rz_bin_te_obj_t *bin) { default: return rz_str_dup("unknown"); } - return machine; } char *rz_bin_te_get_os(struct rz_bin_te_obj_t *bin) { diff --git a/librz/bin/format/te/te.h b/librz/bin/format/te/te.h index a146755adcd..1fb3501b34c 100644 --- a/librz/bin/format/te/te.h +++ b/librz/bin/format/te/te.h @@ -50,6 +50,7 @@ ut64 rz_bin_te_get_main_paddr(struct rz_bin_te_obj_t *bin); ut64 rz_bin_te_get_image_base(struct rz_bin_te_obj_t *bin); int rz_bin_te_get_image_size(struct rz_bin_te_obj_t *bin); char *rz_bin_te_get_machine(struct rz_bin_te_obj_t *bin); +char *rz_bin_te_get_cpu(struct rz_bin_te_obj_t *bin); int rz_bin_te_get_bits(struct rz_bin_te_obj_t *bin); char *rz_bin_te_get_os(struct rz_bin_te_obj_t *bin); struct rz_bin_te_section_t *rz_bin_te_get_sections(struct rz_bin_te_obj_t *bin); diff --git a/librz/bin/p/bin_avr.c b/librz/bin/p/bin_avr.c index fa36f0e857e..7b3d96445a9 100644 --- a/librz/bin/p/bin_avr.c +++ b/librz/bin/p/bin_avr.c @@ -132,6 +132,7 @@ static RzBinInfo *info(RzBinFile *bf) { bi->type = rz_str_dup("ROM"); bi->machine = rz_str_dup("ATmel"); bi->os = rz_str_dup("avr"); + bi->cpu = rz_str_dup("ATmega8"); bi->has_va = 0; // 1; bi->arch = rz_str_dup("avr"); bi->bits = 8; diff --git a/librz/bin/p/bin_coff.c b/librz/bin/p/bin_coff.c index b1e9c5b12cf..1693700f5a8 100644 --- a/librz/bin/p/bin_coff.c +++ b/librz/bin/p/bin_coff.c @@ -416,11 +416,20 @@ static RzBinInfo *info(RzBinFile *bf) { switch (obj->hdr.f_magic) { case COFF_FILE_MACHINE_R4000: + ret->cpu = rz_str_dup("mips4"); + /* fall-thru */ case COFF_FILE_MACHINE_MIPS16: + if (!ret->cpu) { + ret->cpu = rz_str_dup("mips16"); + } + /* fall-thru */ case COFF_FILE_MACHINE_MIPSFPU: case COFF_FILE_MACHINE_MIPSFPU16: ret->machine = rz_str_dup("mips"); ret->arch = rz_str_dup("mips"); + if (!ret->cpu) { + ret->cpu = rz_str_dup("mips32"); + } ret->bits = 32; break; case COFF_FILE_MACHINE_I386: diff --git a/librz/bin/p/bin_elf.inc b/librz/bin/p/bin_elf.inc index 5f330b736d5..72c47d1094a 100644 --- a/librz/bin/p/bin_elf.inc +++ b/librz/bin/p/bin_elf.inc @@ -2100,6 +2100,10 @@ static RzBinInfo *info(RzBinFile *bf) { } if ((str = Elf_(rz_bin_elf_get_abi)(obj))) { ret->features = str; + if (!ret->has_pi) { + // Elf MIPS PIE flag is in features. + ret->has_pi = (strstr(str, "pic ")) ? 1 : 0; + } } ret->rclass = rz_str_dup("elf"); diff --git a/librz/bin/p/bin_mach0.c b/librz/bin/p/bin_mach0.c index 0ff3b3ee246..841a5e429d4 100644 --- a/librz/bin/p/bin_mach0.c +++ b/librz/bin/p/bin_mach0.c @@ -470,7 +470,8 @@ static RzBinInfo *info(RzBinFile *bf) { ret->rclass = rz_str_dup("mach0"); ret->os = rz_str_dup("darwin"); ret->subsystem = rz_str_dup(MACH0_(get_platform)(bf->o->bin_obj)); - ret->arch = rz_str_dup(MACH0_(get_cputype)(bf->o->bin_obj)); + ret->arch = strdup(MACH0_(get_cputype)(bf->o->bin_obj)); + ret->cpu = MACH0_(get_cpusubtype)(bf->o->bin_obj); ret->machine = MACH0_(get_cpusubtype)(bf->o->bin_obj); ret->type = MACH0_(get_filetype)(bf->o->bin_obj); ret->big_endian = MACH0_(is_big_endian)(bf->o->bin_obj); diff --git a/librz/bin/p/bin_psxexe.c b/librz/bin/p/bin_psxexe.c index 92116989a6a..fd9cd2f7762 100644 --- a/librz/bin/p/bin_psxexe.c +++ b/librz/bin/p/bin_psxexe.c @@ -39,6 +39,7 @@ static RzBinInfo *info(RzBinFile *bf) { ret->machine = rz_str_dup("Sony PlayStation 1"); ret->os = rz_str_dup("psx"); ret->arch = rz_str_dup("mips"); + ret->cpu = strdup("mips3"); ret->bits = 32; ret->has_va = true; return ret; diff --git a/librz/bin/p/bin_te.c b/librz/bin/p/bin_te.c index cd69afcdd4a..78800d18004 100644 --- a/librz/bin/p/bin_te.c +++ b/librz/bin/p/bin_te.c @@ -128,6 +128,7 @@ static RzBinInfo *info(RzBinFile *bf) { ret->os = rz_bin_te_get_os(bf->o->bin_obj); ret->arch = rz_bin_te_get_arch(bf->o->bin_obj); ret->machine = rz_bin_te_get_machine(bf->o->bin_obj); + ret->cpu = rz_bin_te_get_cpu(bf->o->bin_obj); ret->subsystem = rz_bin_te_get_subsystem(bf->o->bin_obj); ret->type = rz_str_dup("EXEC (Executable file)"); ret->bits = rz_bin_te_get_bits(bf->o->bin_obj); diff --git a/librz/core/cbin.c b/librz/core/cbin.c index d9af06a80da..656a6f60b80 100644 --- a/librz/core/cbin.c +++ b/librz/core/cbin.c @@ -304,7 +304,7 @@ RZ_API bool rz_core_bin_apply_all_info(RzCore *r, RzBinFile *binfile) { rz_config_set(r->config, "asm.arch", arch); rz_config_set_i(r->config, "asm.bits", bits); rz_config_set(r->config, "analysis.arch", arch); - if (info->cpu && *info->cpu) { + if (RZ_STR_ISNOTEMPTY(info->cpu)) { rz_config_set(r->config, "analysis.cpu", info->cpu); } else { rz_config_set(r->config, "analysis.cpu", arch); @@ -585,10 +585,10 @@ RZ_API bool rz_core_bin_apply_config(RzCore *r, RzBinFile *binfile) { rz_config_set(r->config, "analysis.cpp.abi", "itanium"); } rz_config_set(r->config, "asm.arch", info->arch); - if (info->cpu && *info->cpu) { + if (RZ_STR_ISNOTEMPTY(info->cpu)) { rz_config_set(r->config, "asm.cpu", info->cpu); } - if (info->features && *info->features) { + if (RZ_STR_ISNOTEMPTY(info->features)) { rz_config_set(r->config, "asm.features", info->features); } rz_config_set(r->config, "analysis.arch", info->arch); @@ -3092,6 +3092,7 @@ RZ_API bool rz_core_bin_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile case RZ_OUTPUT_MODE_QUIET: rz_cons_printf("arch %s\n", info->arch); rz_cons_printf("cpu %s\n", str2na(info->cpu)); + rz_cons_printf("features %s\n", str2na(info->features)); rz_cons_printf("bits %d\n", bits); rz_cons_printf("os %s\n", info->os); rz_cons_printf("endian %s\n", info->big_endian ? "big" : "little"); @@ -3116,6 +3117,9 @@ RZ_API bool rz_core_bin_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile if (RZ_STR_ISNOTEMPTY(info->cpu)) { pj_ks(pj, "cpu", info->cpu); } + if (RZ_STR_ISNOTEMPTY(info->features)) { + pj_ks(pj, "features", info->features); + } pj_kn(pj, "baddr", rz_bin_get_baddr(core->bin)); pj_kn(pj, "binsz", rz_bin_get_size(core->bin)); if (RZ_STR_ISNOTEMPTY(info->rclass)) { @@ -3249,6 +3253,7 @@ RZ_API bool rz_core_bin_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile rz_table_add_rowf(t, "ss", "arch", str2na(info->arch)); rz_table_add_rowf(t, "ss", "cpu", str2na(info->cpu)); + rz_table_add_rowf(t, "ss", "features", str2na(info->features)); rz_table_add_rowf(t, "sX", "baddr", rz_bin_get_baddr(core->bin)); rz_table_add_rowf(t, "sX", "binsz", rz_bin_get_size(core->bin)); rz_table_add_rowf(t, "ss", "bintype", str2na(info->rclass)); @@ -5265,8 +5270,8 @@ static void print_arch(RzBin *bin, RzCmdStateOutput *state, struct arch_ctx *ctx pj_ki(state->d.pj, "bits", ctx->bits); pj_kn(state->d.pj, "offset", ctx->offset); pj_kn(state->d.pj, "size", ctx->size); - if (info && !strcmp(ctx->arch, "mips")) { - pj_ks(state->d.pj, "isa", info->cpu); + if (info) { + pj_ks(state->d.pj, "cpu", info->cpu); pj_ks(state->d.pj, "features", info->features); } if (ctx->machine) { diff --git a/librz/core/cconfig.c b/librz/core/cconfig.c index e1975e7d685..7cb89858bb9 100644 --- a/librz/core/cconfig.c +++ b/librz/core/cconfig.c @@ -481,6 +481,32 @@ static bool cb_asm_varfold(void *core, void *node) { return false; } +static void handle_supported_cpus(RzConfig *config, const char *supported, const char *cpu, const char *arch) { + // strdup is required when calling rz_config_set, because it will free the old value + char *cpu_copy = rz_str_dup(cpu); + + // we need to duplicate supported because rz_str_split_list will modify the string. + char *supported_copy = rz_str_dup(supported); + RzList *cpu_list = rz_str_split_list(supported_copy, ",", 0); + RzListIter *it = NULL; + const char *lcpu = NULL; + rz_list_foreach (cpu_list, it, lcpu) { + if (!strcmp(lcpu, cpu_copy)) { + rz_config_set(config, "asm.cpu", cpu_copy); + break; + } + } + + if (lcpu && strcmp(lcpu, cpu_copy) != 0) { + RZ_LOG_INFO("asm.cpu: unknown cpu '%s' for arch '%s'\n", cpu_copy, arch); + rz_config_set(config, "asm.cpu", ""); + } + + rz_list_free(cpu_list); + free(supported_copy); + free(cpu_copy); +} + static bool cb_asmarch(void *user, void *data) { char asmparser[32]; RzCore *core = (RzCore *)user; @@ -515,29 +541,16 @@ static bool cb_asmarch(void *user, void *data) { RZ_LOG_ERROR("core: asm.arch: cannot find (%s)\n", node->value); return false; } - - RzConfigNode *asm_cpu_node = rz_config_node_get(core->config, "asm.cpu"); + char *asm_cpu = rz_str_dup(rz_config_get(core->config, "asm.cpu")); if (core->rasm->cur) { - const char *cpus = core->rasm->cur->cpus; - if (asm_cpu_node) { - if (RZ_STR_ISNOTEMPTY(cpus)) { - if ((asm_cpu_node->value && strstr(cpus, asm_cpu_node->value) == NULL) || RZ_STR_ISEMPTY(asm_cpu_node->value)) { - char *cpu0 = rz_str_dup(cpus); - char *comma = strchr(cpu0, ','); - if (comma) { - *comma = 0; - } - - if (!*asm_cpu_node->value || (*asm_cpu_node->value && RZ_STR_NE(cpu0, asm_cpu_node->value))) { - rz_config_set(core->config, "asm.cpu", cpu0); - } - free(cpu0); - } - } else if (cpus && !*cpus) { - rz_config_set(core->config, "asm.cpu", ""); - } + const char *cpus_supported = core->rasm->cur->cpus; + if (RZ_STR_ISNOTEMPTY(cpus_supported) && + RZ_STR_ISNOTEMPTY(asm_cpu)) { + handle_supported_cpus(core->config, cpus_supported, asm_cpu, node->value); + } else { + rz_config_set(core->config, "asm.cpu", ""); + RZ_FREE(asm_cpu); } - bits = core->rasm->cur->bits; if (8 & bits) { bits = 8; @@ -549,7 +562,15 @@ static bool cb_asmarch(void *user, void *data) { bits = 64; } update_asmbits_options(core, rz_config_node_get(core->config, "asm.bits")); + } else { + rz_config_set(core->config, "asm.cpu", ""); + RZ_FREE(asm_cpu); } + + if (core->analysis) { + rz_syscall_setup(core->analysis->syscall, node->value, bits, asm_cpu, asmos); + } + snprintf(asmparser, sizeof(asmparser), "%s.pseudo", node->value); rz_config_set(core->config, "asm.parser", asmparser); if (core->rasm->cur && core->analysis && @@ -595,9 +616,11 @@ static bool cb_asmarch(void *user, void *data) { // set endian of display to match binary core->print->big_endian = big_endian; - rz_asm_set_cpu(core->rasm, asm_cpu_node->value); - if (asm_cpu_node) { - update_asmcpu_options(core, asm_cpu_node); + rz_asm_set_cpu(core->rasm, asm_cpu); + free(asm_cpu); + RzConfigNode *asmcpu = rz_config_node_get(core->config, "asm.cpu"); + if (asmcpu) { + update_asmcpu_options(core, asmcpu); } { int v = rz_analysis_archinfo(core->analysis, RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN); @@ -620,11 +643,11 @@ static bool cb_asmarch(void *user, void *data) { rz_core_analysis_cc_init(core); const char *platform = rz_config_get(core->config, "asm.platform"); - if (asm_cpu_node) { + if (asmcpu) { char *platforms_dir = rz_path_system(RZ_SDB_ARCH_PLATFORMS); char *cpus_dir = rz_path_system(RZ_SDB_ARCH_CPUS); - rz_platform_target_index_init(core->analysis->platform_target, node->value, asm_cpu_node->value, platform, platforms_dir); - rz_platform_profiles_init(core->analysis->arch_target, asm_cpu_node->value, node->value, cpus_dir); + rz_platform_target_index_init(core->analysis->platform_target, node->value, asmcpu->value, platform, platforms_dir); + rz_platform_profiles_init(core->analysis->arch_target, asmcpu->value, node->value, cpus_dir); free(cpus_dir); free(platforms_dir); } @@ -731,8 +754,10 @@ static bool cb_asmfeatures(void *user, void *data) { return 0; } RZ_FREE(core->rasm->features); + RZ_FREE(core->analysis->features); if (node->value[0]) { core->rasm->features = rz_str_dup(node->value); + core->analysis->features = rz_str_dup(node->value); } return 1; } diff --git a/librz/core/cesil.c b/librz/core/cesil.c index 111deb6182d..25192c37520 100644 --- a/librz/core/cesil.c +++ b/librz/core/cesil.c @@ -200,7 +200,7 @@ RZ_API int rz_core_esil_step(RzCore *core, ut64 until_addr, const char *until_ex // branches are illegal in a delay slot esil->trap = RZ_ANALYSIS_TRAP_EXEC_ERR; esil->trap_code = addr; - RZ_LOG_WARN("core: ESIL: Trap, trying to execute a branch in a delay slot\n"); + RZ_LOG_INFO("core: ESIL: Trap, trying to execute a branch in a delay slot\n"); return_tail(1); break; } diff --git a/librz/core/golang.c b/librz/core/golang.c index 5a6094bdd67..c0797332786 100644 --- a/librz/core/golang.c +++ b/librz/core/golang.c @@ -1870,6 +1870,7 @@ RZ_API void rz_core_analysis_resolve_golang_strings(RzCore *core) { recover_cb = &golang_recover_string_x64; break; default: + RZ_LOG_WARN("golang: string recovery for %s bits %d is not implemented.\n", asm_arch, asm_bits); break; } } else if (!strcmp(asm_arch, "arm")) { @@ -1881,6 +1882,7 @@ RZ_API void rz_core_analysis_resolve_golang_strings(RzCore *core) { recover_cb = &golang_recover_string_arm64; break; default: + RZ_LOG_WARN("golang: string recovery for %s bits %d is not implemented.\n", asm_arch, asm_bits); break; } } else if (!strcmp(asm_arch, "mips")) { @@ -1892,6 +1894,7 @@ RZ_API void rz_core_analysis_resolve_golang_strings(RzCore *core) { recover_cb = &golang_recover_string_mips64; break; default: + RZ_LOG_WARN("golang: string recovery for %s bits %d is not implemented.\n", asm_arch, asm_bits); break; } } else if (!strcmp(asm_arch, "riscv")) { @@ -1900,6 +1903,7 @@ RZ_API void rz_core_analysis_resolve_golang_strings(RzCore *core) { recover_cb = &golang_recover_string_riscv64; break; default: + RZ_LOG_WARN("golang: string recovery for %s bits %d is not implemented.\n", asm_arch, asm_bits); break; } } else if (!strcmp(asm_arch, "ppc")) { @@ -1908,6 +1912,7 @@ RZ_API void rz_core_analysis_resolve_golang_strings(RzCore *core) { recover_cb = &golang_recover_string_ppc64; break; default: + RZ_LOG_WARN("golang: string recovery for %s bits %d is not implemented.\n", asm_arch, asm_bits); break; } } else if (!strcmp(asm_arch, "sysz")) { diff --git a/librz/include/rz_analysis.h b/librz/include/rz_analysis.h index 5e922d86183..7ffb530f47c 100644 --- a/librz/include/rz_analysis.h +++ b/librz/include/rz_analysis.h @@ -467,6 +467,7 @@ typedef struct rz_analysis_t { // NOTE: Do not change the order of fields above! // They are used in pointer passing hacks in rz_types.h. char *cpu; // analysis.cpu + char *features; // analysis.features char *os; // asm.os int bits; // asm.bits int lineswidth; // asm.lines.width diff --git a/test/db/analysis/java b/test/db/analysis/java index f0a5ce94bfa..c2d5c2600a0 100644 --- a/test/db/analysis/java +++ b/test/db/analysis/java @@ -194,6 +194,7 @@ block 0x100 type JAVA CLASS arch java cpu N/A +features N/A baddr 0x00000000 binsz 0x00000400 bintype class diff --git a/test/db/analysis/mips b/test/db/analysis/mips index fdf040f3353..aca78e8c50f 100644 --- a/test/db/analysis/mips +++ b/test/db/analysis/mips @@ -1,910 +1,75 @@ -NAME=mips hello reference analysis +NAME=mips ensure correct cpu is selected FILE=bins/elf/analysis/mips-hello CMDS=< /dev/null -pdf -EOF -EXPECT=< /dev/null -pd 10 -afl -EOF -EXPECT=</dev/null -pdf -EOF -EXPECT=< /dev/null -pdf -EOF -EXPECT=< /dev/null -pdf -EOF -EXPECT=< /dev/null -pdf -EOF -EXPECT=< /dev/null -pdf -EOF -EXPECT=< /dev/null -pdf -EOF -EXPECT=< /dev/null -pd 38 -EOF -EXPECT=< /dev/null -pd 38 -EOF -EXPECT=< /dev/null -pd 38 -EOF -EXPECT=< /dev/null -pd 38 -EOF -EXPECT=< 0x000804fc b 0x804fc +\ 0x00080500 nop + ; UNKNOWN XREF from section..dynsym @ +0xb4 + ; DATA XREF from sym.do_mips_start @ 0x80544 +/ int main(int argc, char **argv, char **envp); +| ; arg int argc @ a0 | ; var int32_t var_10h @ stack - 0x10 -| ; var int32_t var_ch @ stack - 0xc | ; var int32_t var_8h @ stack - 0x8 | ; var int32_t var_4h @ stack - 0x4 -| 0x00000794 lui gp, 2 -| 0x00000798 addiu gp, gp, -0x7db4 -| 0x0000079c addu gp, gp, t9 -| 0x000007a0 addiu sp, sp, -0x30 -| 0x000007a4 sw ra, 0x2c(sp) -| 0x000007a8 sw fp, 0x28(sp) -| 0x000007ac move fp, sp -| 0x000007b0 sw gp, 0x10(sp) -| 0x000007b4 addiu v0, zero, 1 -| 0x000007b8 sw v0, 0x18(fp) -| 0x000007bc addiu v0, zero, 2 -| 0x000007c0 sw v0, 0x1c(fp) -| 0x000007c4 addiu v0, zero, 3 -| 0x000007c8 sw v0, 0x20(fp) -| 0x000007cc addiu v0, zero, 4 -| 0x000007d0 sw v0, 0x24(fp) -| 0x000007d4 lw v0, -sym.leaffunc(gp) -| 0x000007d8 move t9, v0 -| 0x000007dc bal sym.leaffunc -| 0x000007e0 nop -| 0x000007e4 lw gp, 0x10(fp) -| 0x000007e8 lw v0, 0x24(fp) -| 0x000007ec sw v0, 0x1c(fp) -| 0x000007f0 lw v0, 0x18(fp) -| 0x000007f4 move sp, fp -| 0x000007f8 lw ra, 0x2c(sp) -| 0x000007fc lw fp, 0x28(sp) -| 0x00000800 addiu sp, sp, 0x30 -| 0x00000804 jr ra -\ 0x00000808 nop -afvR - var_4h 0x7f8 - var_8h 0x7fc - var_20h 0x7e4 - var_18h 0x7f0 - var_14h - var_10h - var_ch 0x7e8 -afvW - var_4h 0x7a4 - var_8h 0x7a8 - var_20h 0x7b0 - var_18h 0x7b8 - var_14h 0x7c0,0x7ec - var_10h 0x7c8 - var_ch 0x7d0 -EOF -RUN - -NAME=aav without vinfun -FILE=bins/elf/analysis/mipsbe-busybox -CMDS=<