nouveau/mme: Add initial Fermi definition
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
@@ -18,12 +18,12 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
mme_isa_depend_files = [
|
||||
mme_tu104_isa_depend_files = [
|
||||
'mme_tu104.xml',
|
||||
isaspec_py_deps
|
||||
]
|
||||
|
||||
mme_isa = custom_target(
|
||||
mme_tu104_isa = custom_target(
|
||||
'mme_isa',
|
||||
input: ['mme_tu104.xml'],
|
||||
output: ['mme_tu104_isa.c', 'mme_tu104_isa.h'],
|
||||
@@ -31,21 +31,50 @@ mme_isa = custom_target(
|
||||
prog_isaspec_decode, '--xml', '@INPUT@',
|
||||
'--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@',
|
||||
],
|
||||
depend_files: mme_isa_depend_files,
|
||||
depend_files: mme_tu104_isa_depend_files,
|
||||
)
|
||||
|
||||
mme_encode_h = custom_target(
|
||||
mme_tu104_encode_h = custom_target(
|
||||
'mme-tu104-encode.h',
|
||||
input: ['mme_tu104.xml'],
|
||||
output: 'mme_tu104_encode.h',
|
||||
command: [
|
||||
prog_isaspec_encode, '--xml', '@INPUT@', '--out-h', '@OUTPUT@'
|
||||
],
|
||||
depend_files: mme_isa_depend_files,
|
||||
depend_files: mme_tu104_isa_depend_files,
|
||||
)
|
||||
|
||||
mme_fermi_isa_depend_files = [
|
||||
'mme_fermi.xml',
|
||||
isaspec_py_deps
|
||||
]
|
||||
|
||||
mme_fermi_isa = custom_target(
|
||||
'mme_fermi_isa',
|
||||
input: ['mme_fermi.xml'],
|
||||
output: ['mme_fermi_isa.c', 'mme_fermi_isa.h'],
|
||||
command: [
|
||||
prog_isaspec_decode, '--xml', '@INPUT@',
|
||||
'--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@',
|
||||
],
|
||||
depend_files: mme_fermi_isa_depend_files,
|
||||
)
|
||||
|
||||
mme_fermi_encode_h = custom_target(
|
||||
'mme-fermi-encode.h',
|
||||
input: ['mme_fermi.xml'],
|
||||
output: 'mme_fermi_encode.h',
|
||||
command: [
|
||||
prog_isaspec_encode, '--xml', '@INPUT@', '--out-h', '@OUTPUT@'
|
||||
],
|
||||
depend_files: mme_fermi_isa_depend_files,
|
||||
)
|
||||
|
||||
libnouveau_mme_files = files(
|
||||
'mme_builder.h',
|
||||
'mme_fermi.c',
|
||||
'mme_fermi.h',
|
||||
'mme_fermi_dump.c',
|
||||
'mme_tu104.c',
|
||||
'mme_tu104.h',
|
||||
'mme_tu104_builder.c',
|
||||
@@ -56,7 +85,13 @@ libnouveau_mme_files = files(
|
||||
|
||||
_libnouveau_mme = static_library(
|
||||
'nouveau_mme',
|
||||
[libnouveau_mme_files, mme_isa, mme_encode_h],
|
||||
[
|
||||
libnouveau_mme_files,
|
||||
mme_fermi_isa,
|
||||
mme_fermi_encode_h,
|
||||
mme_tu104_isa,
|
||||
mme_tu104_encode_h,
|
||||
],
|
||||
include_directories : [inc_include, inc_src],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
dependencies : [
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
#include "mme_fermi.h"
|
||||
#include "mme_fermi_encode.h"
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#define OP_TO_STR(OP) [MME_FERMI_OP_##OP] = #OP
|
||||
static const char *op_to_str[] = {
|
||||
OP_TO_STR(ALU_REG),
|
||||
OP_TO_STR(ADD_IMM),
|
||||
OP_TO_STR(MERGE),
|
||||
OP_TO_STR(BFE_LSL_IMM),
|
||||
OP_TO_STR(BFE_LSL_REG),
|
||||
OP_TO_STR(STATE),
|
||||
OP_TO_STR(UNK6),
|
||||
OP_TO_STR(BRANCH),
|
||||
};
|
||||
#undef OP_TO_STR
|
||||
|
||||
const char *
|
||||
mme_fermi_op_to_str(enum mme_fermi_op op)
|
||||
{
|
||||
assert(op < ARRAY_SIZE(op_to_str));
|
||||
return op_to_str[op];
|
||||
}
|
||||
|
||||
#define ALU_OP_TO_STR(OP) [MME_FERMI_ALU_OP_##OP] = #OP
|
||||
static const char *alu_op_to_str[] = {
|
||||
ALU_OP_TO_STR(ADD),
|
||||
ALU_OP_TO_STR(ADDC),
|
||||
ALU_OP_TO_STR(SUB),
|
||||
ALU_OP_TO_STR(SUBB),
|
||||
ALU_OP_TO_STR(RESERVED4),
|
||||
ALU_OP_TO_STR(RESERVED5),
|
||||
ALU_OP_TO_STR(RESERVED6),
|
||||
ALU_OP_TO_STR(RESERVED7),
|
||||
ALU_OP_TO_STR(XOR),
|
||||
ALU_OP_TO_STR(OR),
|
||||
ALU_OP_TO_STR(AND),
|
||||
ALU_OP_TO_STR(AND_NOT),
|
||||
ALU_OP_TO_STR(NAND),
|
||||
ALU_OP_TO_STR(RESERVED13),
|
||||
ALU_OP_TO_STR(RESERVED14),
|
||||
ALU_OP_TO_STR(RESERVED15),
|
||||
ALU_OP_TO_STR(RESERVED16),
|
||||
ALU_OP_TO_STR(RESERVED17),
|
||||
ALU_OP_TO_STR(RESERVED18),
|
||||
ALU_OP_TO_STR(RESERVED19),
|
||||
ALU_OP_TO_STR(RESERVED20),
|
||||
ALU_OP_TO_STR(RESERVED21),
|
||||
ALU_OP_TO_STR(RESERVED22),
|
||||
ALU_OP_TO_STR(RESERVED23),
|
||||
ALU_OP_TO_STR(RESERVED24),
|
||||
ALU_OP_TO_STR(RESERVED25),
|
||||
ALU_OP_TO_STR(RESERVED26),
|
||||
ALU_OP_TO_STR(RESERVED27),
|
||||
ALU_OP_TO_STR(RESERVED28),
|
||||
ALU_OP_TO_STR(RESERVED29),
|
||||
ALU_OP_TO_STR(RESERVED30),
|
||||
ALU_OP_TO_STR(RESERVED31),
|
||||
};
|
||||
#undef ALU_OP_TO_STR
|
||||
|
||||
const char *
|
||||
mme_fermi_alu_op_to_str(enum mme_fermi_alu_op op)
|
||||
{
|
||||
assert(op < ARRAY_SIZE(alu_op_to_str));
|
||||
return alu_op_to_str[op];
|
||||
}
|
||||
|
||||
#define ASSIGN_OP_TO_STR(OP) [MME_FERMI_ASSIGN_OP_##OP] = #OP
|
||||
static const char *assign_op_to_str[] = {
|
||||
ASSIGN_OP_TO_STR(LOAD),
|
||||
ASSIGN_OP_TO_STR(MOVE),
|
||||
ASSIGN_OP_TO_STR(MOVE_SET_MADDR),
|
||||
ASSIGN_OP_TO_STR(LOAD_EMIT),
|
||||
ASSIGN_OP_TO_STR(MOVE_EMIT),
|
||||
ASSIGN_OP_TO_STR(LOAD_SET_MADDR),
|
||||
ASSIGN_OP_TO_STR(MOVE_SET_MADDR_LOAD_EMIT),
|
||||
ASSIGN_OP_TO_STR(MOVE_SET_MADDR_LOAD_EMIT_HIGH),
|
||||
};
|
||||
#undef ASSIGN_OP_TO_STR
|
||||
|
||||
const char *
|
||||
mme_fermi_assign_op_to_str(enum mme_fermi_assign_op op)
|
||||
{
|
||||
assert(op < ARRAY_SIZE(assign_op_to_str));
|
||||
return assign_op_to_str[op];
|
||||
}
|
||||
|
||||
void mme_fermi_encode(uint32_t *out, uint32_t inst_count,
|
||||
const struct mme_fermi_inst *insts)
|
||||
{
|
||||
for (uint32_t i = 0; i < inst_count; i++) {
|
||||
bitmask_t enc = encode__instruction(NULL, NULL, insts[i]);
|
||||
out[i] = enc.bitset[0];
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
unpack_field(bitmask_t bitmask, unsigned low, unsigned high, bool is_signed)
|
||||
{
|
||||
bitmask_t field, mask;
|
||||
|
||||
assert(high >= low);
|
||||
|
||||
BITSET_ZERO(mask.bitset);
|
||||
BITSET_SET_RANGE(mask.bitset, 0, high - low);
|
||||
|
||||
BITSET_COPY(field.bitset, bitmask.bitset);
|
||||
BITSET_SHR(field.bitset, low);
|
||||
BITSET_AND(field.bitset, field.bitset, mask.bitset);
|
||||
|
||||
uint64_t data = bitmask_to_uint64_t(field);
|
||||
if (is_signed)
|
||||
data = util_sign_extend(data, high - low + 1);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void mme_fermi_decode(struct mme_fermi_inst *insts,
|
||||
const uint32_t *in, uint32_t inst_count)
|
||||
{
|
||||
for (uint32_t i = 0; i < inst_count; i++) {
|
||||
bitmask_t enc = { .bitset = { in[i] }};
|
||||
|
||||
insts[i].op = unpack_field(enc, 0, 3, false);
|
||||
insts[i].end_next = unpack_field(enc, 7, 7, false);
|
||||
insts[i].dst = unpack_field(enc, 8, 10, false);
|
||||
|
||||
if (insts[i].op != MME_FERMI_OP_BRANCH) {
|
||||
insts[i].assign_op = unpack_field(enc, 4, 6, false);
|
||||
}
|
||||
|
||||
if (insts[i].op == MME_FERMI_OP_ALU_REG) {
|
||||
insts[i].src[0] = unpack_field(enc, 11, 13, false);
|
||||
insts[i].src[1] = unpack_field(enc, 14, 16, false);
|
||||
insts[i].alu_op = unpack_field(enc, 17, 21, false);
|
||||
} else if (insts[i].op == MME_FERMI_OP_ADD_IMM ||
|
||||
insts[i].op == MME_FERMI_OP_STATE) {
|
||||
insts[i].src[0] = unpack_field(enc, 11, 13, false);
|
||||
insts[i].imm = unpack_field(enc, 14, 31, false);
|
||||
} else if (insts[i].op == MME_FERMI_OP_MERGE ||
|
||||
insts[i].op == MME_FERMI_OP_BFE_LSL_IMM ||
|
||||
insts[i].op == MME_FERMI_OP_BFE_LSL_REG) {
|
||||
insts[i].src[0] = unpack_field(enc, 11, 13, false);
|
||||
insts[i].src[1] = unpack_field(enc, 14, 16, false);
|
||||
insts[i].bitfield.src_bit = unpack_field(enc, 17, 21, false);
|
||||
insts[i].bitfield.size = unpack_field(enc, 22, 26, false);
|
||||
insts[i].bitfield.dst_bit = unpack_field(enc, 27, 31, false);
|
||||
} else if (insts[i].op == MME_FERMI_OP_BRANCH) {
|
||||
insts[i].branch.not_zero = unpack_field(enc, 4, 4, false);
|
||||
insts[i].branch.no_delay = unpack_field(enc, 5, 5, false);
|
||||
insts[i].src[0] = unpack_field(enc, 11, 13, false);
|
||||
insts[i].imm = unpack_field(enc, 14, 31, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_indent(FILE *fp, unsigned depth)
|
||||
{
|
||||
for (unsigned i = 0; i < depth; i++)
|
||||
fprintf(fp, " ");
|
||||
}
|
||||
|
||||
static void
|
||||
print_reg(FILE *fp, enum mme_fermi_reg reg)
|
||||
{
|
||||
if (reg == MME_FERMI_REG_ZERO) {
|
||||
fprintf(fp, " $zero");
|
||||
} else {
|
||||
fprintf(fp, " $r%u", (unsigned)reg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_imm(FILE *fp, const struct mme_fermi_inst *inst)
|
||||
{
|
||||
int32_t imm = util_mask_sign_extend(inst->imm, 18);
|
||||
|
||||
fprintf(fp, " %d /* 0x%04x */", (int)imm, (unsigned)imm);
|
||||
}
|
||||
|
||||
void
|
||||
mme_fermi_print_inst(FILE *fp, unsigned indent,
|
||||
const struct mme_fermi_inst *inst)
|
||||
{
|
||||
print_indent(fp, indent);
|
||||
|
||||
switch (inst->op) {
|
||||
case MME_FERMI_OP_ALU_REG:
|
||||
fprintf(fp, "%s", mme_fermi_alu_op_to_str(inst->alu_op));
|
||||
print_reg(fp, inst->src[0]);
|
||||
print_reg(fp, inst->src[1]);
|
||||
|
||||
if (inst->alu_op == MME_FERMI_ALU_OP_ADDC) {
|
||||
fprintf(fp, " $carry");
|
||||
} else if (inst->alu_op == MME_FERMI_ALU_OP_SUBB) {
|
||||
fprintf(fp, " $borrow");
|
||||
}
|
||||
break;
|
||||
case MME_FERMI_OP_ADD_IMM:
|
||||
case MME_FERMI_OP_STATE:
|
||||
fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
|
||||
print_reg(fp, inst->src[0]);
|
||||
print_imm(fp, inst);
|
||||
break;
|
||||
case MME_FERMI_OP_MERGE:
|
||||
uint32_t src_bit = inst->bitfield.src_bit;
|
||||
uint32_t size = inst->bitfield.size;
|
||||
uint32_t dst_bit = inst->bitfield.dst_bit;
|
||||
|
||||
fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
|
||||
print_reg(fp, inst->src[0]);
|
||||
print_reg(fp, inst->src[1]);
|
||||
fprintf(fp, " (%u, %u, %u)", src_bit, size, dst_bit);
|
||||
break;
|
||||
case MME_FERMI_OP_BFE_LSL_IMM:
|
||||
fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
|
||||
print_reg(fp, inst->src[0]);
|
||||
print_reg(fp, inst->src[1]);
|
||||
fprintf(fp, " (%u, %u)", inst->bitfield.dst_bit,
|
||||
inst->bitfield.size);
|
||||
break;
|
||||
case MME_FERMI_OP_BFE_LSL_REG:
|
||||
fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
|
||||
print_reg(fp, inst->src[0]);
|
||||
print_reg(fp, inst->src[1]);
|
||||
fprintf(fp, " (%u, %u)", inst->bitfield.src_bit,
|
||||
inst->bitfield.size);
|
||||
break;
|
||||
case MME_FERMI_OP_BRANCH:
|
||||
if (inst->branch.not_zero) {
|
||||
fprintf(fp, "BNZ");
|
||||
} else {
|
||||
fprintf(fp, "BZ");
|
||||
}
|
||||
print_reg(fp, inst->src[0]);
|
||||
print_imm(fp, inst);
|
||||
|
||||
if (inst->branch.no_delay) {
|
||||
fprintf(fp, " NO_DELAY");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst->op != MME_FERMI_OP_BRANCH) {
|
||||
fprintf(fp, "\n");
|
||||
print_indent(fp, indent);
|
||||
|
||||
fprintf(fp, "%s", mme_fermi_assign_op_to_str(inst->assign_op));
|
||||
print_reg(fp, inst->dst);
|
||||
|
||||
if (inst->assign_op != MME_FERMI_ASSIGN_OP_LOAD) {
|
||||
fprintf(fp, " $scratch");
|
||||
}
|
||||
}
|
||||
|
||||
if (inst->end_next) {
|
||||
fprintf(fp, "\n");
|
||||
print_indent(fp, indent);
|
||||
fprintf(fp, "END_NEXT");
|
||||
}
|
||||
|
||||
fprintf(fp, "\n");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
mme_fermi_print(FILE *fp, const struct mme_fermi_inst *insts,
|
||||
uint32_t inst_count)
|
||||
{
|
||||
for (uint32_t i = 0; i < inst_count; i++) {
|
||||
fprintf(fp, "%u:\n", i);
|
||||
mme_fermi_print_inst(fp, 1, &insts[i]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#ifndef MME_FERMI_H
|
||||
#define MME_FERMI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "util/macros.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define MME_FERMI_DRAM_COUNT 0xc00
|
||||
#define MME_FERMI_SCRATCH_COUNT 128
|
||||
|
||||
enum PACKED mme_fermi_reg {
|
||||
MME_FERMI_REG_ZERO,
|
||||
MME_FERMI_REG_R1,
|
||||
MME_FERMI_REG_R2,
|
||||
MME_FERMI_REG_R3,
|
||||
MME_FERMI_REG_R4,
|
||||
MME_FERMI_REG_R5,
|
||||
MME_FERMI_REG_R6,
|
||||
MME_FERMI_REG_R7,
|
||||
};
|
||||
|
||||
enum PACKED mme_fermi_op {
|
||||
MME_FERMI_OP_ALU_REG,
|
||||
MME_FERMI_OP_ADD_IMM,
|
||||
MME_FERMI_OP_MERGE,
|
||||
MME_FERMI_OP_BFE_LSL_IMM,
|
||||
MME_FERMI_OP_BFE_LSL_REG,
|
||||
MME_FERMI_OP_STATE,
|
||||
MME_FERMI_OP_UNK6,
|
||||
MME_FERMI_OP_BRANCH,
|
||||
};
|
||||
|
||||
const char *mme_fermi_op_to_str(enum mme_fermi_op op);
|
||||
|
||||
enum PACKED mme_fermi_alu_op {
|
||||
MME_FERMI_ALU_OP_ADD,
|
||||
MME_FERMI_ALU_OP_ADDC,
|
||||
MME_FERMI_ALU_OP_SUB,
|
||||
MME_FERMI_ALU_OP_SUBB,
|
||||
MME_FERMI_ALU_OP_RESERVED4,
|
||||
MME_FERMI_ALU_OP_RESERVED5,
|
||||
MME_FERMI_ALU_OP_RESERVED6,
|
||||
MME_FERMI_ALU_OP_RESERVED7,
|
||||
MME_FERMI_ALU_OP_XOR,
|
||||
MME_FERMI_ALU_OP_OR,
|
||||
MME_FERMI_ALU_OP_AND,
|
||||
MME_FERMI_ALU_OP_AND_NOT,
|
||||
MME_FERMI_ALU_OP_NAND,
|
||||
MME_FERMI_ALU_OP_RESERVED13,
|
||||
MME_FERMI_ALU_OP_RESERVED14,
|
||||
MME_FERMI_ALU_OP_RESERVED15,
|
||||
MME_FERMI_ALU_OP_RESERVED16,
|
||||
MME_FERMI_ALU_OP_RESERVED17,
|
||||
MME_FERMI_ALU_OP_RESERVED18,
|
||||
MME_FERMI_ALU_OP_RESERVED19,
|
||||
MME_FERMI_ALU_OP_RESERVED20,
|
||||
MME_FERMI_ALU_OP_RESERVED21,
|
||||
MME_FERMI_ALU_OP_RESERVED22,
|
||||
MME_FERMI_ALU_OP_RESERVED23,
|
||||
MME_FERMI_ALU_OP_RESERVED24,
|
||||
MME_FERMI_ALU_OP_RESERVED25,
|
||||
MME_FERMI_ALU_OP_RESERVED26,
|
||||
MME_FERMI_ALU_OP_RESERVED27,
|
||||
MME_FERMI_ALU_OP_RESERVED28,
|
||||
MME_FERMI_ALU_OP_RESERVED29,
|
||||
MME_FERMI_ALU_OP_RESERVED30,
|
||||
MME_FERMI_ALU_OP_RESERVED31,
|
||||
};
|
||||
|
||||
const char *mme_fermi_alu_op_to_str(enum mme_fermi_alu_op op);
|
||||
|
||||
|
||||
enum PACKED mme_fermi_assign_op {
|
||||
MME_FERMI_ASSIGN_OP_LOAD,
|
||||
MME_FERMI_ASSIGN_OP_MOVE,
|
||||
MME_FERMI_ASSIGN_OP_MOVE_SET_MADDR,
|
||||
MME_FERMI_ASSIGN_OP_LOAD_EMIT,
|
||||
MME_FERMI_ASSIGN_OP_MOVE_EMIT,
|
||||
MME_FERMI_ASSIGN_OP_LOAD_SET_MADDR,
|
||||
MME_FERMI_ASSIGN_OP_MOVE_SET_MADDR_LOAD_EMIT,
|
||||
MME_FERMI_ASSIGN_OP_MOVE_SET_MADDR_LOAD_EMIT_HIGH,
|
||||
};
|
||||
|
||||
const char *mme_fermi_assign_op_to_str(enum mme_fermi_assign_op op);
|
||||
|
||||
struct mme_fermi_bitfield {
|
||||
uint8_t src_bit;
|
||||
uint8_t size;
|
||||
uint8_t dst_bit;
|
||||
};
|
||||
|
||||
struct mme_fermi_branch {
|
||||
bool not_zero;
|
||||
bool no_delay;
|
||||
};
|
||||
|
||||
struct mme_fermi_inst {
|
||||
bool end_next;
|
||||
enum mme_fermi_assign_op assign_op;
|
||||
enum mme_fermi_op op;
|
||||
enum mme_fermi_reg dst;
|
||||
enum mme_fermi_reg src[2];
|
||||
int32_t imm;
|
||||
union {
|
||||
enum mme_fermi_alu_op alu_op;
|
||||
struct mme_fermi_bitfield bitfield;
|
||||
struct mme_fermi_branch branch;
|
||||
};
|
||||
};
|
||||
|
||||
#define MME_FERMI_INST_DEFAULTS \
|
||||
.end_next = false, \
|
||||
.assign_op = MME_FERMI_ASSIGN_OP_MOVE, \
|
||||
.op = MME_FERMI_OP_ALU_REG, \
|
||||
.dst = MME_FERMI_REG_ZERO, \
|
||||
.src = { \
|
||||
MME_FERMI_REG_ZERO, \
|
||||
MME_FERMI_REG_ZERO \
|
||||
}, \
|
||||
.imm = 0, \
|
||||
.alu_op = MME_FERMI_ALU_OP_ADD, \
|
||||
|
||||
void mme_fermi_print_inst(FILE *fp, unsigned indent,
|
||||
const struct mme_fermi_inst *inst);
|
||||
|
||||
void mme_fermi_print(FILE *fp, const struct mme_fermi_inst *insts,
|
||||
uint32_t inst_count);
|
||||
|
||||
void mme_fermi_encode(uint32_t *out, uint32_t inst_count,
|
||||
const struct mme_fermi_inst *insts);
|
||||
|
||||
void mme_fermi_decode(struct mme_fermi_inst *insts,
|
||||
const uint32_t *in, uint32_t inst_count);
|
||||
|
||||
void mme_fermi_dump(FILE *fp, uint32_t *encoded, size_t encoded_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MME_FERMI_H */
|
||||
@@ -0,0 +1,219 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 marysaka <mary@mary.zone>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
-->
|
||||
<isa>
|
||||
<enum name="#reg">
|
||||
<value val="0" display="zero"/>
|
||||
<value val="1" display="r1"/>
|
||||
<value val="2" display="r2"/>
|
||||
<value val="3" display="r3"/>
|
||||
<value val="4" display="r4"/>
|
||||
<value val="5" display="r5"/>
|
||||
<value val="6" display="r6"/>
|
||||
<value val="7" display="r7"/>
|
||||
</enum>
|
||||
|
||||
<enum name="#op">
|
||||
<value val="0" display="ALU_REG"/>
|
||||
<value val="1" display="ADD_IMM"/>
|
||||
<value val="2" display="MERGE"/>
|
||||
<value val="3" display="BFE_LSL_IMM"/>
|
||||
<value val="4" display="BFE_LSL_REG"/>
|
||||
<value val="5" display="STATE"/>
|
||||
<!-- TODO: There seems to be something here (no fault is generated) -->
|
||||
<value val="6" display="UNK6"/>
|
||||
<value val="7" display="BRANCH"/>
|
||||
</enum>
|
||||
|
||||
<enum name="#alu-op">
|
||||
<value val="0" display="ADD"/>
|
||||
<value val="1" display="ADDC"/>
|
||||
<value val="2" display="SUB"/>
|
||||
<value val="3" display="SUBB"/>
|
||||
<!-- value val="4" display="reserved4"/ -->
|
||||
<!-- value val="5" display="reserved5"/ -->
|
||||
<!-- value val="6" display="reserved6"/ -->
|
||||
<!-- value val="7" display="reserved7"/ -->
|
||||
<value val="8" display="XOR"/>
|
||||
<value val="9" display="OR"/>
|
||||
<value val="10" display="AND"/>
|
||||
<value val="11" display="AND_NOT"/>
|
||||
<value val="12" display="NAND"/>
|
||||
<!-- value val="13" display="reserved13"/ -->
|
||||
<!-- value val="14" display="reserved14"/ -->
|
||||
<!-- value val="15" display="reserved15"/ -->
|
||||
<!-- value val="16" display="reserved16"/ -->
|
||||
<!-- value val="17" display="reserved17"/ -->
|
||||
<!-- value val="18" display="reserved18"/ -->
|
||||
<!-- value val="19" display="reserved19"/ -->
|
||||
<!-- value val="20" display="reserved20"/ -->
|
||||
<!-- value val="21" display="reserved21"/ -->
|
||||
<!-- value val="22" display="reserved22"/ -->
|
||||
<!-- value val="23" display="reserved23"/ -->
|
||||
<!-- value val="24" display="reserved24"/ -->
|
||||
<!-- value val="25" display="reserved25"/ -->
|
||||
<!-- value val="26" display="reserved26"/ -->
|
||||
<!-- value val="27" display="reserved27"/ -->
|
||||
<!-- value val="28" display="reserved28"/ -->
|
||||
<!-- value val="29" display="reserved29"/ -->
|
||||
<!-- value val="30" display="reserved30"/ -->
|
||||
<!-- value val="31" display="reserved31"/ -->
|
||||
</enum>
|
||||
|
||||
<enum name="#assign-op">
|
||||
<value val="0" display="LOAD"/>
|
||||
<value val="1" display="MOVE"/>
|
||||
<value val="2" display="MOVE_SET_MADDR"/>
|
||||
<value val="3" display="LOAD_EMIT"/>
|
||||
<value val="4" display="MOVE_EMIT"/>
|
||||
<value val="5" display="LOAD_SET_MADDR"/>
|
||||
<value val="6" display="MOVE_SET_MADDR_LOAD_EMIT"/>
|
||||
<value val="7" display="MOVE_SET_MADDR_LOAD_EMIT_HIGH"/>
|
||||
</enum>
|
||||
|
||||
<bitset name="#alu-instruction" size="18">
|
||||
<display>
|
||||
{NAME} {ASSIGN_OP} {ALU_OP} {DST} {SRC0} {SRC1}
|
||||
</display>
|
||||
|
||||
<field name="ASSIGN_OP" low="0" high="2" type="#assign-op"/>
|
||||
<pattern low="3" high="3">x</pattern>
|
||||
<field name="DST" low="4" high="6" type="#reg"/>
|
||||
<field name="SRC0" low="7" high="9" type="#reg"/>
|
||||
<field name="SRC1" low="10" high="12" type="#reg"/>
|
||||
<field name="ALU_OP" low="13" high="17" type="#alu-op"/>
|
||||
|
||||
<encode type="struct mme_fermi_inst">
|
||||
<map name="ASSIGN_OP">src.assign_op</map>
|
||||
<map name="ALU_OP">src.alu_op</map>
|
||||
<map name="DST">src.dst</map>
|
||||
<map name="SRC0">src.src[0]</map>
|
||||
<map name="SRC1">src.src[1]</map>
|
||||
</encode>
|
||||
</bitset>
|
||||
|
||||
<bitset name="#src0-imm-encoding" size="28">
|
||||
<display>
|
||||
{NAME} {ASSIGN_OP} {DST} {SRC0} {IMM}
|
||||
</display>
|
||||
|
||||
<field name="ASSIGN_OP" low="0" high="2" type="#assign-op"/>
|
||||
<pattern low="3" high="3">x</pattern>
|
||||
<field name="DST" low="4" high="6" type="#reg"/>
|
||||
<field name="SRC0" low="7" high="9" type="#reg"/>
|
||||
<field name="IMM" low="10" high="27" type="int"/>
|
||||
|
||||
<encode type="struct mme_fermi_inst">
|
||||
<map name="ASSIGN_OP">src.assign_op</map>
|
||||
<map name="DST">src.dst</map>
|
||||
<map name="SRC0">src.src[0]</map>
|
||||
<map name="IMM">src.imm</map>
|
||||
</encode>
|
||||
</bitset>
|
||||
|
||||
<bitset name="#bf-encoding" size="28">
|
||||
<display>
|
||||
{NAME} {ASSIGN_OP} {DST} {SRC0} {SRC1} {BF_SRC_BIT} {BF_SIZE} {BF_DST_BIT}
|
||||
</display>
|
||||
|
||||
<field name="ASSIGN_OP" low="0" high="2" type="#assign-op"/>
|
||||
<pattern low="3" high="3">x</pattern>
|
||||
<field name="DST" low="4" high="6" type="#reg"/>
|
||||
<field name="SRC0" low="7" high="9" type="#reg"/>
|
||||
<field name="SRC1" low="10" high="12" type="#reg"/>
|
||||
<field name="BF_SRC_BIT" low="13" high="17" type="uint"/>
|
||||
<field name="BF_SIZE" low="18" high="22" type="uint"/>
|
||||
<field name="BF_DST_BIT" low="23" high="27" type="uint"/>
|
||||
|
||||
<encode type="struct mme_fermi_inst">
|
||||
<map name="ASSIGN_OP">src.assign_op</map>
|
||||
<map name="DST">src.dst</map>
|
||||
<map name="SRC0">src.src[0]</map>
|
||||
<map name="SRC1">src.src[1]</map>
|
||||
<map name="BF_SRC_BIT">src.bitfield.src_bit</map>
|
||||
<map name="BF_SIZE">src.bitfield.size</map>
|
||||
<map name="BF_DST_BIT">src.bitfield.dst_bit</map>
|
||||
</encode>
|
||||
</bitset>
|
||||
|
||||
<bitset name="#branch-encoding" size="28">
|
||||
<display>
|
||||
{NO_DELAY} B{NOT_ZERO} {SRC0} {IMM}
|
||||
</display>
|
||||
|
||||
<field name="NOT_ZERO" pos="0" type="bool" display="Z"/>
|
||||
<field name="NO_DELAY" pos="1" type="bool" display="NO_DELAY"/>
|
||||
<pattern low="2" high="6">xxxxx</pattern>
|
||||
<field name="SRC0" low="7" high="9" type="#reg"/>
|
||||
<field name="IMM" low="10" high="27" type="int"/>
|
||||
|
||||
<encode type="struct mme_fermi_inst">
|
||||
<map name="NOT_ZERO">src.branch.not_zero</map>
|
||||
<map name="NO_DELAY">src.branch.no_delay</map>
|
||||
<map name="SRC0">src.src[0]</map>
|
||||
<map name="IMM">src.imm</map>
|
||||
</encode>
|
||||
</bitset>
|
||||
|
||||
<bitset name="#instruction" size="32">
|
||||
<doc>
|
||||
Encoding of a NVIDIA Fermi Macro Method instruction. All instructions are 32b.
|
||||
</doc>
|
||||
<display>
|
||||
{END_NEXT} {OP} {ALU_OP_ENCODING} {SRC0_IMM_ENCODING} {BF_ENCODING} {BRANCH_ENCODING}
|
||||
</display>
|
||||
<field name="OP" low="0" high="3" type="#op"/>
|
||||
<pattern low="4" high="6">xxx</pattern>
|
||||
<field name="END_NEXT" pos="7" type="bool" display="(end-next)"/>
|
||||
<pattern low="8" high="31">xxxxxxxxxxxxxxxxxxxxxxxx</pattern>
|
||||
|
||||
<override>
|
||||
<expr>{OP} == 0</expr>
|
||||
<field name="ALU_OP_ENCODING" low="4" high="21" type="#alu-instruction" />
|
||||
</override>
|
||||
|
||||
<override>
|
||||
<expr>{OP} == 1 || {OP} == 5</expr>
|
||||
<field name="SRC0_IMM_ENCODING" low="4" high="31" type="#src0-imm-encoding" />
|
||||
</override>
|
||||
|
||||
<override>
|
||||
<expr>{OP} == 2 || {OP} == 3 || {OP} == 4</expr>
|
||||
<field name="BF_ENCODING" low="4" high="31" type="#bf-encoding" />
|
||||
</override>
|
||||
|
||||
<override>
|
||||
<expr>{OP} == 7</expr>
|
||||
<field name="BRANCH_ENCODING" low="4" high="31" type="#branch-encoding" />
|
||||
</override>
|
||||
|
||||
<encode type="struct mme_fermi_inst">
|
||||
<map name="END_NEXT">src.end_next</map>
|
||||
<map name="OP">src.op</map>
|
||||
<map name="ALU_OP_ENCODING">src</map>
|
||||
<map name="SRC0_IMM_ENCODING">src</map>
|
||||
<map name="BF_ENCODING">src</map>
|
||||
<map name="BRANCH_ENCODING">src</map>
|
||||
</encode>
|
||||
</bitset>
|
||||
</isa>
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "mme_fermi.h"
|
||||
|
||||
#include "mme_fermi_isa.h"
|
||||
#include "isa.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void
|
||||
disasm_instr_cb(void *d, unsigned n, void *instr)
|
||||
{
|
||||
fprintf(d, "%3d[%08x]", n, *(uint32_t *)instr);
|
||||
}
|
||||
|
||||
void
|
||||
mme_fermi_dump(FILE *fp, uint32_t *encoded, size_t encoded_size)
|
||||
{
|
||||
const struct isa_decode_options opts = {
|
||||
.show_errors = true,
|
||||
.branch_labels = true,
|
||||
.cbdata = fp,
|
||||
.pre_instr_cb = disasm_instr_cb,
|
||||
};
|
||||
isa_disasm(encoded, encoded_size, fp, &opts);
|
||||
}
|
||||
Reference in New Issue
Block a user