/* Return 2 if the condition can't be simplified, and the result of the condition (0 or 1) if it can */ static TCGArg do_constant_folding_cond(TCGContext *s, TCGOpcode op, TCGArg x, TCGArg y, TCGCond c) { struct tcg_temp_info *temps = s->temps2; if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) { switch (op_bits(s, op)) { case 32: return do_constant_folding_cond_32(temps[x].val, temps[y].val, c); case 64: return do_constant_folding_cond_64(temps[x].val, temps[y].val, c); default: tcg_abort(); } } else if (temps_are_copies(s, x, y)) { return do_constant_folding_cond_eq(c); } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) { switch (c) { case TCG_COND_LTU: return 0; case TCG_COND_GEU: return 1; default: return 2; } } else { return 2; } }
static TCGArg do_constant_folding(TCGContext *s, TCGOpcode op, TCGArg x, TCGArg y) { TCGArg res = do_constant_folding_2(op, x, y); if (op_bits(s, op) == 32) { res &= 0xffffffff; } return res; }
static TCGOpcode op_to_movi(TCGContext *s, TCGOpcode op) { switch (op_bits(s, op)) { case 32: return INDEX_op_movi_i32; case 64: return INDEX_op_movi_i64; default: fprintf(stderr, "op_to_movi: unexpected return value of " "function op_bits.\n"); tcg_abort(); } }
void disasm_mips_instruction(u32 opcode, char *buffer, u32 pc) { int opcode_type = opcode >> 26; if(opcode == 0) { sprintf(buffer, "nop"); return; } switch(mips_opcode_types[opcode_type]) { case MIPS_OPCODE_ALU_IMMS: { u32 rs = op_bits(reg_rs, 0x1F); if((opcode_type == 0x9) && (rs == 0)) { sprintf(buffer, "li %s, %d", reg_op(reg_rt), imms()); } else { sprintf(buffer, "%s %s, %s, %d", mips_opcode_names[opcode_type], reg_op(reg_rt), mips_reg_names[rs], imms()); } break; } case MIPS_OPCODE_ALU_IMMU: { sprintf(buffer, "%s %s, %s, 0x%x", mips_opcode_names[opcode_type], reg_op(reg_rt), reg_op(reg_rs), immu()); break; } case MIPS_OPCODE_ALU2_IMMU: { sprintf(buffer, "%s %s, 0x%x", mips_opcode_names[opcode_type], reg_op(reg_rt), immu()); break; } case MIPS_OPCODE_REGIMM: { u32 function = op_bits(16, 0x1F); sprintf(buffer, "%s %s, %08x", mips_function_regimm_names[function], reg_op(reg_rs), pc_offset()); break; } case MIPS_OPCODE_SPECIAL: { mips_function_special_type function = (mips_function_special_type)op_bits(0, 0x3F); switch(mips_function_special_types[function]) { case MIPS_SPECIAL_FUNCTION_ALU: { sprintf(buffer, "%s %s, %s, %s", mips_function_special_names[function], reg_op(reg_rd), reg_op(reg_rs), reg_op(reg_rt)); break; } case MIPS_SPECIAL_FUNCTION_MUL_DIV: { sprintf(buffer, "%s %s, %s", mips_function_special_names[function], reg_op(reg_rs), reg_op(reg_rt)); break; } case MIPS_SPECIAL_FUNCTION_JALR: { u32 rd = op_bits(reg_rd, 0x1F); if(rd == 31) { sprintf(buffer, "%s %s", mips_function_special_names[function], reg_op(reg_rs)); } else { sprintf(buffer, "%s %s, %s", mips_function_special_names[function], mips_reg_names[rd], reg_op(reg_rs)); } break; } case MIPS_SPECIAL_FUNCTION_JR: { sprintf(buffer, "%s %s", mips_function_special_names[function], reg_op(reg_rs)); break; } case MIPS_SPECIAL_FUNCTION_HI_LO: { sprintf(buffer, "%s %s", mips_function_special_names[function], reg_op(reg_rd)); break; } case MIPS_SPECIAL_FUNCTION_SHIFT: { sprintf(buffer, "%s %s, %s, %d", mips_function_special_names[function], reg_op(reg_rd), reg_op(reg_rt), op_bits(6, 0x1F)); break; } default: { sprintf(buffer, "unknown"); break; } } break; } case MIPS_OPCODE_BRANCH: { u32 offset = op_bits(0, 0x3FFFFFF); offset = (offset << 2) | ((pc + 4) & 0xFC000000); sprintf(buffer, "%s %08x", mips_opcode_names[opcode_type], offset); break; } case MIPS_OPCODE_BRANCHC: { sprintf(buffer, "%s %s, %08x", mips_opcode_names[opcode_type], reg_op(reg_rs), pc_offset()); break; } case MIPS_OPCODE_BRANCHC2: { sprintf(buffer, "%s %s, %s, %08x", mips_opcode_names[opcode_type], reg_op(reg_rs), reg_op(reg_rt), pc_offset()); break; } case MIPS_OPCODE_MEM: { s32 offset = signed_offset(); if(offset < 0) { sprintf(buffer, "%s %s, [%s - %d]", mips_opcode_names[opcode_type], reg_op(reg_rt), reg_op(reg_rs), -offset); } else { sprintf(buffer, "%s %s, [%s + %d]", mips_opcode_names[opcode_type], reg_op(reg_rt), reg_op(reg_rs), offset); } break; } default: { sprintf(buffer, "unknown"); break; } } }