blob: 90e63b836746fa71f4ded9550e0aed65788701d1 [file] [log] [blame]
/*
* Source file for nanoMIPS disassembler component of QEMU
*
* Copyright (C) 2018 Wave Computing, Inc.
* Copyright (C) 2018 Matthew Fortune <matthew.fortune@mips.com>
* Copyright (C) 2018 Aleksandar Markovic <amarkovic@wavecomp.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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, see <https://www.gnu.org/licenses/>.
*
*/
/*
* Documentation used while implementing this component:
*
* [1] "MIPS® Architecture Base: nanoMIPS32(tm) Instruction Set Technical
* Reference Manual", Revision 01.01, April 27, 2018
*/
extern "C" {
#include "qemu/osdep.h"
#include "disas/dis-asm.h"
}
#include <cstring>
#include <stdexcept>
#include <sstream>
#include <stdio.h>
#include <stdarg.h>
#include "nanomips.h"
#define IMGASSERTONCE(test)
int nanomips_dis(char *buf,
unsigned address,
unsigned short one,
unsigned short two,
unsigned short three)
{
std::string disasm;
uint16 bits[3] = {one, two, three};
NMD::TABLE_ENTRY_TYPE type;
NMD d(address, NMD::ALL_ATTRIBUTES);
int size = d.Disassemble(bits, disasm, type);
strcpy(buf, disasm.c_str());
return size;
}
int print_insn_nanomips(bfd_vma memaddr, struct disassemble_info *info)
{
int status;
bfd_byte buffer[2];
uint16_t insn1 = 0, insn2 = 0, insn3 = 0;
char buf[200];
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;
}
if (info->endian == BFD_ENDIAN_BIG) {
insn1 = bfd_getb16(buffer);
} else {
insn1 = bfd_getl16(buffer);
}
(*info->fprintf_func)(info->stream, "%04x ", insn1);
/* Handle 32-bit opcodes. */
if ((insn1 & 0x1000) == 0) {
status = (*info->read_memory_func)(memaddr + 2, buffer, 2, info);
if (status != 0) {
(*info->memory_error_func)(status, memaddr + 2, info);
return -1;
}
if (info->endian == BFD_ENDIAN_BIG) {
insn2 = bfd_getb16(buffer);
} else {
insn2 = bfd_getl16(buffer);
}
(*info->fprintf_func)(info->stream, "%04x ", insn2);
} else {
(*info->fprintf_func)(info->stream, " ");
}
/* Handle 48-bit opcodes. */
if ((insn1 >> 10) == 0x18) {
status = (*info->read_memory_func)(memaddr + 4, buffer, 2, info);
if (status != 0) {
(*info->memory_error_func)(status, memaddr + 4, info);
return -1;
}
if (info->endian == BFD_ENDIAN_BIG) {
insn3 = bfd_getb16(buffer);
} else {
insn3 = bfd_getl16(buffer);
}
(*info->fprintf_func)(info->stream, "%04x ", insn3);
} else {
(*info->fprintf_func)(info->stream, " ");
}
int length = nanomips_dis(buf, memaddr, insn1, insn2, insn3);
/* FIXME: Should probably use a hash table on the major opcode here. */
(*info->fprintf_func) (info->stream, "%s", buf);
if (length > 0) {
return length / 8;
}
info->insn_type = dis_noninsn;
return insn3 ? 6 : insn2 ? 4 : 2;
}
namespace img
{
address addr32(address a)
{
return a;
}
std::string format(const char *format, ...)
{
char buffer[256];
va_list args;
va_start(args, format);
int err = vsprintf(buffer, format, args);
if (err < 0) {
perror(buffer);
}
va_end(args);
return buffer;
}
std::string format(const char *format,
std::string s)
{
char buffer[256];
sprintf(buffer, format, s.c_str());
return buffer;
}
std::string format(const char *format,
std::string s1,
std::string s2)
{
char buffer[256];
sprintf(buffer, format, s1.c_str(), s2.c_str());
return buffer;
}
std::string format(const char *format,
std::string s1,
std::string s2,
std::string s3)
{
char buffer[256];
sprintf(buffer, format, s1.c_str(), s2.c_str(), s3.c_str());
return buffer;
}
std::string format(const char *format,
std::string s1,
std::string s2,
std::string s3,
std::string s4)
{
char buffer[256];
sprintf(buffer, format, s1.c_str(), s2.c_str(), s3.c_str(),
s4.c_str());
return buffer;
}
std::string format(const char *format,
std::string s1,
std::string s2,
std::string s3,
std::string s4,
std::string s5)
{
char buffer[256];
sprintf(buffer, format, s1.c_str(), s2.c_str(), s3.c_str(),
s4.c_str(), s5.c_str());
return buffer;
}
std::string format(const char *format,
uint64 d,
std::string s2)
{
char buffer[256];
sprintf(buffer, format, d, s2.c_str());
return buffer;
}
std::string format(const char *format,
std::string s1,
uint64 d,
std::string s2)
{
char buffer[256];
sprintf(buffer, format, s1.c_str(), d, s2.c_str());
return buffer;
}
std::string format(const char *format,
std::string s1,
std::string s2,
uint64 d)
{
char buffer[256];
sprintf(buffer, format, s1.c_str(), s2.c_str(), d);
return buffer;
}
char as_char(int c)
{
return static_cast<char>(c);
}
};
std::string to_string(img::address a)
{
char buffer[256];
sprintf(buffer, "0x%" PRIx64, a);
return buffer;
}
uint64 extract_bits(uint64 data, uint32 bit_offset, uint32 bit_size)
{
return (data << (64 - (bit_size + bit_offset))) >> (64 - bit_size);
}
int64 sign_extend(int64 data, int msb)
{
uint64 shift = 63 - msb;
return (data << shift) >> shift;
}
uint64 NMD::renumber_registers(uint64 index, uint64 *register_list,
size_t register_list_size)
{
if (index < register_list_size) {
return register_list[index];
}
throw std::runtime_error(img::format(
"Invalid register mapping index %" PRIu64
", size of list = %zu",
index, register_list_size));
}
/*
* NMD::decode_gpr_gpr4() - decoder for 'gpr4' gpr encoding type
*
* Map a 4-bit code to the 5-bit register space according to this pattern:
*
* 1 0
* 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* | | | | | | | | | | | | | | | |
* | | | | | | | | | | | | | | | |
* | | | | | | | | | | | └---------------┐
* | | | | | | | | | | └---------------┐ |
* | | | | | | | | | └---------------┐ | |
* | | | | | | | | └---------------┐ | | |
* | | | | | | | | | | | | | | | |
* | | | | | | | | | | | | | | | |
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* 3 2 1 0
*
* Used in handling following instructions:
*
* - ADDU[4X4]
* - LW[4X4]
* - MOVEP[REV]
* - MUL[4X4]
* - SW[4X4]
*/
uint64 NMD::decode_gpr_gpr4(uint64 d)
{
static uint64 register_list[] = { 8, 9, 10, 11, 4, 5, 6, 7,
16, 17, 18, 19, 20, 21, 22, 23 };
return renumber_registers(d, register_list,
sizeof(register_list) / sizeof(register_list[0]));
}
/*
* NMD::decode_gpr_gpr4_zero() - decoder for 'gpr4.zero' gpr encoding type
*
* Map a 4-bit code to the 5-bit register space according to this pattern:
*
* 1 0
* 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* | | | | | | | | | | | | | | | |
* | | | | | | | | | | | | └---------------------┐
* | | | | | | | | | | | └---------------┐ |
* | | | | | | | | | | └---------------┐ | |
* | | | | | | | | | └---------------┐ | | |
* | | | | | | | | └---------------┐ | | | |
* | | | | | | | | | | | | | | | |
* | | | | | | | | | | | | | | | |
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* 3 2 1 0
*
* This pattern is the same one used for 'gpr4' gpr encoding type, except for
* the input value 3, that is mapped to the output value 0 instead of 11.
*
* Used in handling following instructions:
*
* - MOVE.BALC
* - MOVEP
* - SW[4X4]
*/
uint64 NMD::decode_gpr_gpr4_zero(uint64 d)
{
static uint64 register_list[] = { 8, 9, 10, 0, 4, 5, 6, 7,
16, 17, 18, 19, 20, 21, 22, 23 };
return renumber_registers(d, register_list,
sizeof(register_list) / sizeof(register_list[0]));
}
/*
* NMD::decode_gpr_gpr3() - decoder for 'gpr3' gpr encoding type
*
* Map a 3-bit code to the 5-bit register space according to this pattern:
*
* 7 6 5 4 3 2 1 0
* | | | | | | | |
* | | | | | | | |
* | | | └-----------------------┐
* | | └-----------------------┐ |
* | └-----------------------┐ | |
* └-----------------------┐ | | |
* | | | | | | | |
* ┌-------┘ | | | | | | |
* | ┌-------┘ | | | | | |
* | | ┌-------┘ | | | | |
* | | | ┌-------┘ | | | |
* | | | | | | | |
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* 3 2 1 0
*
* Used in handling following instructions:
*
* - ADDIU[R1.SP]
* - ADDIU[R2]
* - ADDU[16]
* - AND[16]
* - ANDI[16]
* - BEQC[16]
* - BEQZC[16]
* - BNEC[16]
* - BNEZC[16]
* - LB[16]
* - LBU[16]
* - LH[16]
* - LHU[16]
* - LI[16]
* - LW[16]
* - LW[GP16]
* - LWXS[16]
* - NOT[16]
* - OR[16]
* - SB[16]
* - SH[16]
* - SLL[16]
* - SRL[16]
* - SUBU[16]
* - SW[16]
* - XOR[16]
*/
uint64 NMD::decode_gpr_gpr3(uint64 d)
{
static uint64 register_list[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
return renumber_registers(d, register_list,
sizeof(register_list) / sizeof(register_list[0]));
}
/*
* NMD::decode_gpr_gpr3_src_store() - decoder for 'gpr3.src.store' gpr encoding
* type
*
* Map a 3-bit code to the 5-bit register space according to this pattern:
*
* 7 6 5 4 3 2 1 0
* | | | | | | | |
* | | | | | | | └-----------------------┐
* | | | └-----------------------┐ |
* | | └-----------------------┐ | |
* | └-----------------------┐ | | |
* └-----------------------┐ | | | |
* | | | | | | | |
* ┌-------┘ | | | | | | |
* | ┌-------┘ | | | | | |
* | | ┌-------┘ | | | | |
* | | | | | | | |
* | | | | | | | |
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* 3 2 1 0
*
* This pattern is the same one used for 'gpr3' gpr encoding type, except for
* the input value 0, that is mapped to the output value 0 instead of 16.
*
* Used in handling following instructions:
*
* - SB[16]
* - SH[16]
* - SW[16]
* - SW[GP16]
*/
uint64 NMD::decode_gpr_gpr3_src_store(uint64 d)
{
static uint64 register_list[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
return renumber_registers(d, register_list,
sizeof(register_list) / sizeof(register_list[0]));
}
/*
* NMD::decode_gpr_gpr2_reg1() - decoder for 'gpr2.reg1' gpr encoding type
*
* Map a 2-bit code to the 5-bit register space according to this pattern:
*
* 3 2 1 0
* | | | |
* | | | |
* | | | └-------------------┐
* | | └-------------------┐ |
* | └-------------------┐ | |
* └-------------------┐ | | |
* | | | |
* | | | |
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* 3 2 1 0
*
* Used in handling following instructions:
*
* - MOVEP
* - MOVEP[REV]
*/
uint64 NMD::decode_gpr_gpr2_reg1(uint64 d)
{
static uint64 register_list[] = { 4, 5, 6, 7 };
return renumber_registers(d, register_list,
sizeof(register_list) / sizeof(register_list[0]));
}
/*
* NMD::decode_gpr_gpr2_reg2() - decoder for 'gpr2.reg2' gpr encoding type
*
* Map a 2-bit code to the 5-bit register space according to this pattern:
*
* 3 2 1 0
* | | | |
* | | | |
* | | | └-----------------┐
* | | └-----------------┐ |
* | └-----------------┐ | |
* └-----------------┐ | | |
* | | | |
* | | | |
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* 3 2 1 0
*
* Used in handling following instructions:
*
* - MOVEP
* - MOVEP[REV]
*/
uint64 NMD::decode_gpr_gpr2_reg2(uint64 d)
{
static uint64 register_list[] = { 5, 6, 7, 8 };
return renumber_registers(d, register_list,
sizeof(register_list) / sizeof(register_list[0]));
}
/*
* NMD::decode_gpr_gpr1() - decoder for 'gpr1' gpr encoding type
*
* Map a 1-bit code to the 5-bit register space according to this pattern:
*
* 1 0
* | |
* | |
* | └---------------------┐
* └---------------------┐ |
* | |
* | |
* | |
* | |
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* 3 2 1 0
*
* Used in handling following instruction:
*
* - MOVE.BALC
*/
uint64 NMD::decode_gpr_gpr1(uint64 d)
{
static uint64 register_list[] = { 4, 5 };
return renumber_registers(d, register_list,
sizeof(register_list) / sizeof(register_list[0]));
}
uint64 NMD::copy(uint64 d)
{
return d;
}
int64 NMD::copy(int64 d)
{
return d;
}
int64 NMD::neg_copy(uint64 d)
{
return 0ll - d;
}
int64 NMD::neg_copy(int64 d)
{
return -d;
}
/* strange wrapper around gpr3 */
uint64 NMD::encode_rs3_and_check_rs3_ge_rt3(uint64 d)
{
return decode_gpr_gpr3(d);
}
/* strange wrapper around gpr3 */
uint64 NMD::encode_rs3_and_check_rs3_lt_rt3(uint64 d)
{
return decode_gpr_gpr3(d);
}
/* nop - done by extraction function */
uint64 NMD::encode_s_from_address(uint64 d)
{
return d;
}
/* nop - done by extraction function */
uint64 NMD::encode_u_from_address(uint64 d)
{
return d;
}
/* nop - done by extraction function */
uint64 NMD::encode_s_from_s_hi(uint64 d)
{
return d;
}
uint64 NMD::encode_count3_from_count(uint64 d)
{
IMGASSERTONCE(d < 8);
return d == 0ull ? 8ull : d;
}
uint64 NMD::encode_shift3_from_shift(uint64 d)
{
IMGASSERTONCE(d < 8);
return d == 0ull ? 8ull : d;
}
/* special value for load literal */
int64 NMD::encode_eu_from_s_li16(uint64 d)
{
IMGASSERTONCE(d < 128);
return d == 127 ? -1 : (int64)d;
}
uint64 NMD::encode_msbd_from_size(uint64 d)
{
IMGASSERTONCE(d < 32);
return d + 1;
}
uint64 NMD::encode_eu_from_u_andi16(uint64 d)
{
IMGASSERTONCE(d < 16);
if (d == 12) {
return 0x00ffull;
}
if (d == 13) {
return 0xffffull;
}
return d;
}
uint64 NMD::encode_msbd_from_pos_and_size(uint64 d)
{
IMGASSERTONCE(0);
return d;
}
/* save16 / restore16 ???? */
uint64 NMD::encode_rt1_from_rt(uint64 d)
{
return d ? 31 : 30;
}
/* ? */
uint64 NMD::encode_lsb_from_pos_and_size(uint64 d)
{
return d;
}
std::string NMD::save_restore_list(uint64 rt, uint64 count, uint64 gp)
{
std::string str;
for (uint64 counter = 0; counter != count; counter++) {
bool use_gp = gp && (counter == count - 1);
uint64 this_rt = use_gp ? 28 : ((rt & 0x10) | (rt + counter)) & 0x1f;
str += img::format(",%s", GPR(this_rt));
}
return str;
}
std::string NMD::GPR(uint64 reg)
{
static const char *gpr_reg[32] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "r12", "r13", "r14", "r15",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"r24", "r25", "k0", "k1", "gp", "sp", "fp", "ra"
};
if (reg < 32) {
return gpr_reg[reg];
}
throw std::runtime_error(img::format("Invalid GPR register index %" PRIu64,
reg));
}
std::string NMD::FPR(uint64 reg)
{
static const char *fpr_reg[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"
};
if (reg < 32) {
return fpr_reg[reg];
}
throw std::runtime_error(img::format("Invalid FPR register index %" PRIu64,
reg));
}
std::string NMD::AC(uint64 reg)
{
static const char *ac_reg[4] = {
"ac0", "ac1", "ac2", "ac3"
};
if (reg < 4) {
return ac_reg[reg];
}
throw std::runtime_error(img::format("Invalid AC register index %" PRIu64,
reg));
}
std::string NMD::IMMEDIATE(uint64 value)
{
return img::format("0x%" PRIx64, value);
}
std::string NMD::IMMEDIATE(int64 value)
{
return img::format("%" PRId64, value);
}
std::string NMD::CPR(uint64 reg)
{
/* needs more work */
return img::format("CP%" PRIu64, reg);
}
std::string NMD::ADDRESS(uint64 value, int instruction_size)
{
/* token for string replace */
/* const char TOKEN_REPLACE = (char)0xa2; */
img::address address = m_pc + value + instruction_size;
/* symbol replacement */
/* return img::as_char(TOKEN_REPLACE) + to_string(address); */
return to_string(address);
}
uint64 NMD::extract_op_code_value(const uint16 * data, int size)
{
switch (size) {
case 16:
return data[0];
case 32:
return ((uint64)data[0] << 16) | data[1];
case 48:
return ((uint64)data[0] << 32) | ((uint64)data[1] << 16) | data[2];
default:
return data[0];
}
}
int NMD::Disassemble(const uint16 * data, std::string & dis,
NMD::TABLE_ENTRY_TYPE & type)
{
return Disassemble(data, dis, type, MAJOR, 2);
}
/*
* Recurse through tables until the instruction is found then return
* the string and size
*
* inputs:
* pointer to a word stream,
* disassember table and size
* returns:
* instruction size - negative is error
* disassembly string - on error will constain error string
*/
int NMD::Disassemble(const uint16 * data, std::string & dis,
NMD::TABLE_ENTRY_TYPE & type, const Pool *table,
int table_size)
{
try
{
for (int i = 0; i < table_size; i++) {
uint64 op_code = extract_op_code_value(data,
table[i].instructions_size);
if ((op_code & table[i].mask) == table[i].value) {
/* possible match */
conditional_function cond = table[i].condition;
if ((cond == 0) || (this->*cond)(op_code)) {
try
{
if (table[i].type == pool) {
return Disassemble(data, dis, type,
table[i].next_table,
table[i].next_table_size);
} else if ((table[i].type == instruction) ||
(table[i].type == call_instruction) ||
(table[i].type == branch_instruction) ||
(table[i].type == return_instruction)) {
if ((table[i].attributes != 0) &&
(m_requested_instruction_categories &
table[i].attributes) == 0) {
/*
* failed due to instruction having
* an ASE attribute and the requested version
* not having that attribute
*/
dis = "ASE attribute missmatch";
return -5;
}
disassembly_function dis_fn = table[i].disassembly;
if (dis_fn == 0) {
dis = "disassembler failure - bad table entry";
return -6;
}
type = table[i].type;
dis = (this->*dis_fn)(op_code);
return table[i].instructions_size;
} else {
dis = "reserved instruction";
return -2;
}
}
catch (std::runtime_error & e)
{
dis = e.what();
return -3; /* runtime error */
}
}
}
}
}
catch (std::exception & e)
{
dis = e.what();
return -4; /* runtime error */
}
dis = "failed to disassemble";
return -1; /* failed to disassemble */
}
uint64 NMD::extract_code_18_to_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 19);
return value;
}
uint64 NMD::extract_shift3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 3);
return value;
}
uint64 NMD::extract_u_11_10_9_8_7_6_5_4_3__s3(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 3, 9) << 3;
return value;
}
uint64 NMD::extract_count_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 4);
return value;
}
uint64 NMD::extract_rtz3_9_8_7(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 7, 3);
return value;
}
uint64 NMD::extract_u_17_to_1__s1(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 1, 17) << 1;
return value;
}
int64 NMD::extract_s__se9_20_19_18_17_16_15_14_13_12_11(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 11, 10);
value = sign_extend(value, 9);
return value;
}
int64 NMD::extract_s__se11_0_10_9_8_7_6_5_4_3_2_1_0_s1(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 1) << 11;
value |= extract_bits(instruction, 1, 10) << 1;
value = sign_extend(value, 11);
return value;
}
uint64 NMD::extract_u_10(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 10, 1);
return value;
}
uint64 NMD::extract_rtz4_27_26_25_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 3);
value |= extract_bits(instruction, 25, 1) << 3;
return value;
}
uint64 NMD::extract_sa_15_14_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 5);
return value;
}
uint64 NMD::extract_shift_4_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 5);
return value;
}
uint64 NMD::extract_shiftx_10_9_8_7__s1(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 7, 4) << 1;
return value;
}
uint64 NMD::extract_hint_25_24_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 5);
return value;
}
uint64 NMD::extract_count3_14_13_12(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 12, 3);
return value;
}
int64 NMD::extract_s__se31_0_11_to_2_20_to_12_s12(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 1) << 31;
value |= extract_bits(instruction, 2, 10) << 21;
value |= extract_bits(instruction, 12, 9) << 12;
value = sign_extend(value, 31);
return value;
}
int64 NMD::extract_s__se7_0_6_5_4_3_2_1_s1(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 1) << 7;
value |= extract_bits(instruction, 1, 6) << 1;
value = sign_extend(value, 7);
return value;
}
uint64 NMD::extract_u2_10_9(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 9, 2);
return value;
}
uint64 NMD::extract_code_25_24_23_22_21_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 10);
return value;
}
uint64 NMD::extract_rs_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
uint64 NMD::extract_u_2_1__s1(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 1, 2) << 1;
return value;
}
uint64 NMD::extract_stripe_6(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 6, 1);
return value;
}
uint64 NMD::extract_ac_15_14(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 14, 2);
return value;
}
uint64 NMD::extract_shift_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
uint64 NMD::extract_rdl_25_24(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 24, 1);
return value;
}
int64 NMD::extract_s__se10_0_9_8_7_6_5_4_3_2_1_s1(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 1) << 10;
value |= extract_bits(instruction, 1, 9) << 1;
value = sign_extend(value, 10);
return value;
}
uint64 NMD::extract_eu_6_5_4_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 7);
return value;
}
uint64 NMD::extract_shift_5_4_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 6);
return value;
}
uint64 NMD::extract_count_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 4);
return value;
}
uint64 NMD::extract_code_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 3);
return value;
}
uint64 NMD::extract_u_11_10_9_8_7_6_5_4_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 12);
return value;
}
uint64 NMD::extract_rs_4_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 5);
return value;
}
uint64 NMD::extract_u_20_to_3__s3(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 3, 18) << 3;
return value;
}
uint64 NMD::extract_u_3_2_1_0__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 4) << 2;
return value;
}
uint64 NMD::extract_cofun_25_24_23(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 3, 23);
return value;
}
uint64 NMD::extract_u_2_1_0__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 3) << 2;
return value;
}
uint64 NMD::extract_rd3_3_2_1(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 1, 3);
return value;
}
uint64 NMD::extract_sa_15_14_13_12(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 12, 4);
return value;
}
uint64 NMD::extract_rt_25_24_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 5);
return value;
}
uint64 NMD::extract_ru_7_6_5_4_3(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 3, 5);
return value;
}
uint64 NMD::extract_u_17_to_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 18);
return value;
}
uint64 NMD::extract_rsz4_4_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 3);
value |= extract_bits(instruction, 4, 1) << 3;
return value;
}
int64 NMD::extract_s__se21_0_20_to_1_s1(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 1) << 21;
value |= extract_bits(instruction, 1, 20) << 1;
value = sign_extend(value, 21);
return value;
}
uint64 NMD::extract_op_25_to_3(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 3, 23);
return value;
}
uint64 NMD::extract_rs4_4_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 3);
value |= extract_bits(instruction, 4, 1) << 3;
return value;
}
uint64 NMD::extract_bit_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 3);
return value;
}
uint64 NMD::extract_rt_41_40_39_38_37(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 37, 5);
return value;
}
int64 NMD::extract_shift__se5_21_20_19_18_17_16(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 16, 6);
value = sign_extend(value, 5);
return value;
}
uint64 NMD::extract_rd2_3_8(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 3, 1) << 1;
value |= extract_bits(instruction, 8, 1);
return value;
}
uint64 NMD::extract_code_17_to_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 18);
return value;
}
uint64 NMD::extract_size_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
int64 NMD::extract_s__se8_15_7_6_5_4_3_2_s2(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 2, 6) << 2;
value |= extract_bits(instruction, 15, 1) << 8;
value = sign_extend(value, 8);
return value;
}
uint64 NMD::extract_u_15_to_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 16);
return value;
}
uint64 NMD::extract_fs_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
int64 NMD::extract_s__se8_15_7_6_5_4_3_2_1_0(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 8);
value |= extract_bits(instruction, 15, 1) << 8;
value = sign_extend(value, 8);
return value;
}
uint64 NMD::extract_stype_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
uint64 NMD::extract_rtl_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 9, 1);
return value;
}
uint64 NMD::extract_hs_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
uint64 NMD::extract_sel_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 3);
return value;
}
uint64 NMD::extract_lsb_4_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 5);
return value;
}
uint64 NMD::extract_gp_2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 2, 1);
return value;
}
uint64 NMD::extract_rt3_9_8_7(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 7, 3);
return value;
}
uint64 NMD::extract_ft_25_24_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 5);
return value;
}
uint64 NMD::extract_u_17_16_15_14_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 7);
return value;
}
uint64 NMD::extract_cs_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
uint64 NMD::extract_rt4_9_7_6_5(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 5, 3);
value |= extract_bits(instruction, 9, 1) << 3;
return value;
}
uint64 NMD::extract_msbt_10_9_8_7_6(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 6, 5);
return value;
}
uint64 NMD::extract_u_5_4_3_2_1_0__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 6) << 2;
return value;
}
uint64 NMD::extract_sa_15_14_13(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 13, 3);
return value;
}
int64 NMD::extract_s__se14_0_13_to_1_s1(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 1) << 14;
value |= extract_bits(instruction, 1, 13) << 1;
value = sign_extend(value, 14);
return value;
}
uint64 NMD::extract_rs3_6_5_4(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 4, 3);
return value;
}
uint64 NMD::extract_u_31_to_0__s32(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 32) << 32;
return value;
}
uint64 NMD::extract_shift_10_9_8_7_6(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 6, 5);
return value;
}
uint64 NMD::extract_cs_25_24_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 5);
return value;
}
uint64 NMD::extract_shiftx_11_10_9_8_7_6(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 6, 6);
return value;
}
uint64 NMD::extract_rt_9_8_7_6_5(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 5, 5);
return value;
}
uint64 NMD::extract_op_25_24_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 5);
return value;
}
uint64 NMD::extract_u_6_5_4_3_2_1_0__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 7) << 2;
return value;
}
uint64 NMD::extract_bit_16_15_14_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 6);
return value;
}
uint64 NMD::extract_mask_20_19_18_17_16_15_14(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 14, 7);
return value;
}
uint64 NMD::extract_eu_3_2_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 4);
return value;
}
uint64 NMD::extract_u_7_6_5_4__s4(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 4, 4) << 4;
return value;
}
int64 NMD::extract_s__se8_15_7_6_5_4_3_s3(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 3, 5) << 3;
value |= extract_bits(instruction, 15, 1) << 8;
value = sign_extend(value, 8);
return value;
}
uint64 NMD::extract_ft_15_14_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 5);
return value;
}
int64 NMD::extract_s__se31_15_to_0_31_to_16(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 16) << 16;
value |= extract_bits(instruction, 16, 16);
value = sign_extend(value, 31);
return value;
}
uint64 NMD::extract_u_20_19_18_17_16_15_14_13(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 13, 8);
return value;
}
uint64 NMD::extract_u_17_to_2__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 2, 16) << 2;
return value;
}
uint64 NMD::extract_rd_15_14_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 5);
return value;
}
uint64 NMD::extract_c0s_20_19_18_17_16(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 16, 5);
return value;
}
uint64 NMD::extract_code_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 2);
return value;
}
int64 NMD::extract_s__se25_0_24_to_1_s1(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 1) << 25;
value |= extract_bits(instruction, 1, 24) << 1;
value = sign_extend(value, 25);
return value;
}
uint64 NMD::extract_u_1_0(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 2);
return value;
}
uint64 NMD::extract_u_3_8__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 3, 1) << 3;
value |= extract_bits(instruction, 8, 1) << 2;
return value;
}
uint64 NMD::extract_fd_15_14_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 5);
return value;
}
uint64 NMD::extract_u_4_3_2_1_0__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 5) << 2;
return value;
}
uint64 NMD::extract_rtz4_9_7_6_5(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 5, 3);
value |= extract_bits(instruction, 9, 1) << 3;
return value;
}
uint64 NMD::extract_sel_15_14_13_12_11(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 11, 5);
return value;
}
uint64 NMD::extract_ct_25_24_23_22_21(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 21, 5);
return value;
}
uint64 NMD::extract_u_20_to_2__s2(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 2, 19) << 2;
return value;
}
int64 NMD::extract_s__se3_4_2_1_0(uint64 instruction)
{
int64 value = 0;
value |= extract_bits(instruction, 0, 3);
value |= extract_bits(instruction, 4, 1) << 3;
value = sign_extend(value, 3);
return value;
}
uint64 NMD::extract_u_3_2_1_0__s1(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 0, 4) << 1;
return value;
}
bool NMD::ADDIU_32__cond(uint64 instruction)
{
uint64 rt = extract_rt_25_24_23_22_21(instruction);
return rt != 0;
}
bool NMD::ADDIU_RS5__cond(uint64 instruction)
{
uint64 rt = extract_rt_9_8_7_6_5(instruction);
return rt != 0;
}
bool NMD::BALRSC_cond(uint64 instruction)
{
uint64 rt = extract_rt_25_24_23_22_21(instruction);
return rt != 0;
}
bool NMD::BEQC_16__cond(uint64 instruction)
{
uint64 rs3 = extract_rs3_6_5_4(instruction);
uint64 rt3 = extract_rt3_9_8_7(instruction);
uint64 u = extract_u_3_2_1_0__s1(instruction);
return rs3 < rt3 && u != 0;
}
bool NMD::BNEC_16__cond(uint64 instruction)
{
uint64 rs3 = extract_rs3_6_5_4(instruction);
uint64 rt3 = extract_rt3_9_8_7(instruction);
uint64 u = extract_u_3_2_1_0__s1(instruction);
return rs3 >= rt3 && u != 0;
}
bool NMD::MOVE_cond(uint64 instruction)
{
uint64 rt = extract_rt_9_8_7_6_5(instruction);
return rt != 0;
}
bool NMD::P16_BR1_cond(uint64 instruction)
{
uint64 u = extract_u_3_2_1_0__s1(instruction);
return u != 0;
}
bool NMD::PREF_S9__cond(uint64 instruction)
{
uint64 hint = extract_hint_25_24_23_22_21(instruction);
return hint != 31;
}
bool NMD::PREFE_cond(uint64 instruction)
{
uint64 hint = extract_hint_25_24_23_22_21(instruction);
return hint != 31;
}
bool NMD::SLTU_cond(uint64 instruction)
{
uint64 rd = extract_rd_15_14_13_12_11(instruction);
return rd != 0;
}
/*
* ABS.D fd, fs - Floating Point Absolute Value
*
* 3 2 1
* 10987654321098765432109876543210
* 010001 00000 000101
* fmt -----
* fs -----
* fd -----
*/
std::string NMD::ABS_D(uint64 instruction)
{
uint64 fd_value = extract_ft_25_24_23_22_21(instruction);
uint64 fs_value = extract_fs_20_19_18_17_16(instruction);
std::string fs = FPR(copy(fs_value));
std::string fd = FPR(copy(fd_value));
return img::format("ABS.D %s, %s", fd, fs);
}
/*
* ABS.S fd, fs - Floating Point Absolute Value
*
* 3 2 1
* 10987654321098765432109876543210
* 010001 00000 000101
* fmt -----
* fd -----
* fs -----
*/
std::string NMD::ABS_S(uint64 instruction)
{
uint64 fd_value = extract_ft_25_24_23_22_21(instruction);
uint64 fs_value = extract_fs_20_19_18_17_16(instruction);
std::string fs = FPR(copy(fs_value));
std::string fd = FPR(copy(fd_value));
return img::format("ABS.S %s, %s", fd, fs);
}
/*
* [DSP] ABSQ_S.PH rt, rs - Find absolute value of two fractional halfwords
* with 16-bit saturation
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0001000100111111
* rt -----
* rs -----
*/
std::string NMD::ABSQ_S_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
return img::format("ABSQ_S.PH %s, %s", rt, rs);
}
/*
* [DSP] ABSQ_S.QB rt, rs - Find absolute value of four fractional byte values
* with 8-bit saturation
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0000000100111111
* rt -----
* rs -----
*/
std::string NMD::ABSQ_S_QB(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
return img::format("ABSQ_S.QB %s, %s", rt, rs);
}
/*
* [DSP] ABSQ_S.W rt, rs - Find absolute value of fractional word with 32-bit
* saturation
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ABSQ_S_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
return img::format("ABSQ_S.W %s, %s", rt, rs);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ACLR(uint64 instruction)
{
uint64 bit_value = extract_bit_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
int64 s_value = extract_s__se8_15_7_6_5_4_3_2_1_0(instruction);
std::string bit = IMMEDIATE(copy(bit_value));
std::string s = IMMEDIATE(copy(s_value));
std::string rs = GPR(copy(rs_value));
return img::format("ACLR %s, %s(%s)", bit, s, rs);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADD(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADD %s, %s, %s", rd, rs, rt);
}
/*
* ADD.D fd, fs, ft - Floating Point Add
*
* 3 2 1
* 10987654321098765432109876543210
* 010001 000101
* fmt -----
* ft -----
* fs -----
* fd -----
*/
std::string NMD::ADD_D(uint64 instruction)
{
uint64 ft_value = extract_ft_25_24_23_22_21(instruction);
uint64 fs_value = extract_fs_20_19_18_17_16(instruction);
uint64 fd_value = extract_fd_15_14_13_12_11(instruction);
std::string ft = FPR(copy(ft_value));
std::string fs = FPR(copy(fs_value));
std::string fd = FPR(copy(fd_value));
return img::format("ADD.D %s, %s, %s", fd, fs, ft);
}
/*
* ADD.S fd, fs, ft - Floating Point Add
*
* 3 2 1
* 10987654321098765432109876543210
* 010001 000101
* fmt -----
* ft -----
* fs -----
* fd -----
*/
std::string NMD::ADD_S(uint64 instruction)
{
uint64 ft_value = extract_ft_25_24_23_22_21(instruction);
uint64 fs_value = extract_fs_20_19_18_17_16(instruction);
uint64 fd_value = extract_fd_15_14_13_12_11(instruction);
std::string ft = FPR(copy(ft_value));
std::string fs = FPR(copy(fs_value));
std::string fd = FPR(copy(fd_value));
return img::format("ADD.S %s, %s, %s", fd, fs, ft);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_32_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 u_value = extract_u_15_to_0(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
std::string u = IMMEDIATE(copy(u_value));
return img::format("ADDIU %s, %s, %s", rt, rs, u);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_48_(uint64 instruction)
{
uint64 rt_value = extract_rt_41_40_39_38_37(instruction);
int64 s_value = extract_s__se31_15_to_0_31_to_16(instruction);
std::string rt = GPR(copy(rt_value));
std::string s = IMMEDIATE(copy(s_value));
return img::format("ADDIU %s, %s", rt, s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_GP48_(uint64 instruction)
{
uint64 rt_value = extract_rt_41_40_39_38_37(instruction);
int64 s_value = extract_s__se31_15_to_0_31_to_16(instruction);
std::string rt = GPR(copy(rt_value));
std::string s = IMMEDIATE(copy(s_value));
return img::format("ADDIU %s, $%d, %s", rt, 28, s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_GP_B_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 u_value = extract_u_17_to_0(instruction);
std::string rt = GPR(copy(rt_value));
std::string u = IMMEDIATE(copy(u_value));
return img::format("ADDIU %s, $%d, %s", rt, 28, u);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_GP_W_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 u_value = extract_u_20_to_2__s2(instruction);
std::string rt = GPR(copy(rt_value));
std::string u = IMMEDIATE(copy(u_value));
return img::format("ADDIU %s, $%d, %s", rt, 28, u);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_NEG_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 u_value = extract_u_11_10_9_8_7_6_5_4_3_2_1_0(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
std::string u = IMMEDIATE(neg_copy(u_value));
return img::format("ADDIU %s, %s, %s", rt, rs, u);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_R1_SP_(uint64 instruction)
{
uint64 u_value = extract_u_5_4_3_2_1_0__s2(instruction);
uint64 rt3_value = extract_rt3_9_8_7(instruction);
std::string rt3 = GPR(decode_gpr_gpr3(rt3_value));
std::string u = IMMEDIATE(copy(u_value));
return img::format("ADDIU %s, $%d, %s", rt3, 29, u);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 0010000100111111
* rt -----
* rs -----
*/
std::string NMD::ADDIU_R2_(uint64 instruction)
{
uint64 rt3_value = extract_rt3_9_8_7(instruction);
uint64 rs3_value = extract_rs3_6_5_4(instruction);
uint64 u_value = extract_u_2_1_0__s2(instruction);
std::string rt3 = GPR(decode_gpr_gpr3(rt3_value));
std::string rs3 = GPR(decode_gpr_gpr3(rs3_value));
std::string u = IMMEDIATE(copy(u_value));
return img::format("ADDIU %s, %s, %s", rt3, rs3, u);
}
/*
* ADDIU[RS5] rt, s5 - Add Signed Word and Set Carry Bit
*
* 5432109876543210
* 100100 1
* rt -----
* s - ---
*/
std::string NMD::ADDIU_RS5_(uint64 instruction)
{
uint64 rt_value = extract_rt_9_8_7_6_5(instruction);
int64 s_value = extract_s__se3_4_2_1_0(instruction);
std::string rt = GPR(copy(rt_value));
std::string s = IMMEDIATE(copy(s_value));
return img::format("ADDIU %s, %s", rt, s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDIUPC_32_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
int64 s_value = extract_s__se21_0_20_to_1_s1(instruction);
std::string rt = GPR(copy(rt_value));
std::string s = ADDRESS(encode_s_from_address(s_value), 4);
return img::format("ADDIUPC %s, %s", rt, s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDIUPC_48_(uint64 instruction)
{
uint64 rt_value = extract_rt_41_40_39_38_37(instruction);
int64 s_value = extract_s__se31_15_to_0_31_to_16(instruction);
std::string rt = GPR(copy(rt_value));
std::string s = ADDRESS(encode_s_from_address(s_value), 6);
return img::format("ADDIUPC %s, %s", rt, s);
}
/*
* [DSP] ADDQ.PH rd, rt, rs - Add fractional halfword vectors
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 00000001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDQ_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDQ.PH %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDQ_S.PH rd, rt, rs - Add fractional halfword vectors with 16-bit
* saturation
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 10000001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDQ_S_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDQ_S.PH %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDQ_S.W rd, rt, rs - Add fractional words with 32-bit saturation
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1100000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDQ_S_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDQ_S.W %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDQH.PH rd, rt, rs - Add fractional halfword vectors and shift
* right to halve results
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 00001001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDQH_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDQH.PH %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDQH_R.PH rd, rt, rs - Add fractional halfword vectors and shift
* right to halve results with rounding
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 10001001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDQH_R_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDQH_R.PH %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDQH_R.W rd, rt, rs - Add fractional words and shift right to halve
* results with rounding
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 00010001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDQH_R_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDQH_R.W %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDQH.W rd, rt, rs - Add fractional words and shift right to halve
* results
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 10010001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDQH_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDQH.W %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDSC rd, rt, rs - Add two signed words and set carry bit
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDSC(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDSC %s, %s, %s", rd, rs, rt);
}
/*
* ADDU[16] rd3, rs3, rt3 -
*
* 5432109876543210
* 101100 0
* rt3 ---
* rs3 ---
* rd3 ---
*/
std::string NMD::ADDU_16_(uint64 instruction)
{
uint64 rt3_value = extract_rt3_9_8_7(instruction);
uint64 rs3_value = extract_rs3_6_5_4(instruction);
uint64 rd3_value = extract_rd3_3_2_1(instruction);
std::string rt3 = GPR(decode_gpr_gpr3(rt3_value));
std::string rs3 = GPR(decode_gpr_gpr3(rs3_value));
std::string rd3 = GPR(decode_gpr_gpr3(rd3_value));
return img::format("ADDU %s, %s, %s", rd3, rs3, rt3);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDU_32_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDU %s, %s, %s", rd, rs, rt);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDU_4X4_(uint64 instruction)
{
uint64 rt4_value = extract_rt4_9_7_6_5(instruction);
uint64 rs4_value = extract_rs4_4_2_1_0(instruction);
std::string rs4 = GPR(decode_gpr_gpr4(rs4_value));
std::string rt4 = GPR(decode_gpr_gpr4(rt4_value));
return img::format("ADDU %s, %s", rs4, rt4);
}
/*
* [DSP] ADDU.PH rd, rt, rs - Add two pairs of unsigned halfwords
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 00100001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDU_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDU.PH %s, %s, %s", rd, rs, rt);
}
/*
* ADDU.QB rd, rt, rs - Unsigned Add Quad Byte Vectors
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 00011001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDU_QB(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDU.QB %s, %s, %s", rd, rs, rt);
}
/*
* [DSP] ADDU_S.PH rd, rt, rs - Add two pairs of unsigned halfwords with 16-bit
* saturation
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 10100001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDU_S_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDU_S.PH %s, %s, %s", rd, rs, rt);
}
/*
* ADDU_S.QB rd, rt, rs - Unsigned Add Quad Byte Vectors
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 10011001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDU_S_QB(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDU_S.QB %s, %s, %s", rd, rs, rt);
}
/*
* ADDUH.QB rd, rt, rs - Unsigned Add Vector Quad-Bytes And Right Shift
* to Halve Results
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 00101001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDUH_QB(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDUH.QB %s, %s, %s", rd, rs, rt);
}
/*
* ADDUH_R.QB rd, rt, rs - Unsigned Add Vector Quad-Bytes And Right Shift
* to Halve Results
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 10101001101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDUH_R_QB(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDUH_R.QB %s, %s, %s", rd, rs, rt);
}
/*
* ADDWC rd, rt, rs - Add Word with Carry Bit
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1111000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ADDWC(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("ADDWC %s, %s, %s", rd, rs, rt);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ALUIPC(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
int64 s_value = extract_s__se31_0_11_to_2_20_to_12_s12(instruction);
std::string rt = GPR(copy(rt_value));
std::string s = ADDRESS(encode_s_from_address(s_value), 4);
return img::format("ALUIPC %s, %%pcrel_hi(%s)", rt, s);
}
/*
* AND[16] rt3, rs3 -
*
* 5432109876543210
* 101100
* rt3 ---
* rs3 ---
* eu ----
*/
std::string NMD::AND_16_(uint64 instruction)
{
uint64 rt3_value = extract_rt3_9_8_7(instruction);
uint64 rs3_value = extract_rs3_6_5_4(instruction);
std::string rt3 = GPR(decode_gpr_gpr3(rt3_value));
std::string rs3 = GPR(decode_gpr_gpr3(rs3_value));
return img::format("AND %s, %s", rs3, rt3);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::AND_32_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 rd_value = extract_rd_15_14_13_12_11(instruction);
std::string rd = GPR(copy(rd_value));
std::string rs = GPR(copy(rs_value));
std::string rt = GPR(copy(rt_value));
return img::format("AND %s, %s, %s", rd, rs, rt);
}
/*
* ANDI rt, rs, u -
*
* 5432109876543210
* 101100
* rt3 ---
* rs3 ---
* eu ----
*/
std::string NMD::ANDI_16_(uint64 instruction)
{
uint64 rt3_value = extract_rt3_9_8_7(instruction);
uint64 rs3_value = extract_rs3_6_5_4(instruction);
uint64 eu_value = extract_eu_3_2_1_0(instruction);
std::string rt3 = GPR(decode_gpr_gpr3(rt3_value));
std::string rs3 = GPR(decode_gpr_gpr3(rs3_value));
std::string eu = IMMEDIATE(encode_eu_from_u_andi16(eu_value));
return img::format("ANDI %s, %s, %s", rt3, rs3, eu);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ANDI_32_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 u_value = extract_u_11_10_9_8_7_6_5_4_3_2_1_0(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
std::string u = IMMEDIATE(copy(u_value));
return img::format("ANDI %s, %s, %s", rt, rs, u);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::APPEND(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
uint64 sa_value = extract_sa_15_14_13_12_11(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
std::string sa = IMMEDIATE(copy(sa_value));
return img::format("APPEND %s, %s, %s", rt, rs, sa);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::ASET(uint64 instruction)
{
uint64 bit_value = extract_bit_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
int64 s_value = extract_s__se8_15_7_6_5_4_3_2_1_0(instruction);
std::string bit = IMMEDIATE(copy(bit_value));
std::string s = IMMEDIATE(copy(s_value));
std::string rs = GPR(copy(rs_value));
return img::format("ASET %s, %s(%s)", bit, s, rs);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::BALC_16_(uint64 instruction)
{
int64 s_value = extract_s__se10_0_9_8_7_6_5_4_3_2_1_s1(instruction);
std::string s = ADDRESS(encode_s_from_address(s_value), 2);
return img::format("BALC %s", s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::BALC_32_(uint64 instruction)
{
int64 s_value = extract_s__se25_0_24_to_1_s1(instruction);
std::string s = ADDRESS(encode_s_from_address(s_value), 4);
return img::format("BALC %s", s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::BALRSC(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
std::string rt = GPR(copy(rt_value));
std::string rs = GPR(copy(rs_value));
return img::format("BALRSC %s, %s", rt, rs);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::BBEQZC(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 bit_value = extract_bit_16_15_14_13_12_11(instruction);
int64 s_value = extract_s__se11_0_10_9_8_7_6_5_4_3_2_1_0_s1(instruction);
std::string rt = GPR(copy(rt_value));
std::string bit = IMMEDIATE(copy(bit_value));
std::string s = ADDRESS(encode_s_from_address(s_value), 4);
return img::format("BBEQZC %s, %s, %s", rt, bit, s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::BBNEZC(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 bit_value = extract_bit_16_15_14_13_12_11(instruction);
int64 s_value = extract_s__se11_0_10_9_8_7_6_5_4_3_2_1_0_s1(instruction);
std::string rt = GPR(copy(rt_value));
std::string bit = IMMEDIATE(copy(bit_value));
std::string s = ADDRESS(encode_s_from_address(s_value), 4);
return img::format("BBNEZC %s, %s, %s", rt, bit, s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----
* rs -----
* rd -----
*/
std::string NMD::BC_16_(uint64 instruction)
{
int64 s_value = extract_s__se10_0_9_8_7_6_5_4_3_2_1_s1(instruction);
std::string s = ADDRESS(encode_s_from_address(s_value), 2);
return img::format("BC %s", s);
}
/*
*
*
* 3 2 1
* 10987654321098765432109876543210
* 001000 x1110000101
* rt -----