Ilia Mirkin
2016-Sep-10 18:17 UTC
[Nouveau] [PATCH] gm107: separate out sched decoding from regular ops
Unfortunately there's no sure-fire way to distinguish a sched "op" from regular ones. They happen purely based on position. So for disassembly, use the byte position in the file to determine whether the current op should be decoded as sched or as regular. For assembly, we go back to using a shared table. Ideally we would pick out which one to use based on the position in the outputted bytestream, but it was not apparent to me how to do that. Secondly, it would make it impossible to assembly one plain instruction without first inserting a sched, which would be annoying. Note - this does mean that to decode a gm107 op, one has to supply sched bytes first. However we're nowhere as picky as nvdisasm - zeroes work just fine. --- mwk - this is a little hacky, but seemed like the simplest way to go. Please have a look and let me know if this is OK as is or if I should change it somehow. envydis/core-as.c | 2 +- envydis/core-dis.c | 5 ++++- envydis/gm107.c | 18 ++++++++++++++++-- include/dis.h | 3 +++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/envydis/core-as.c b/envydis/core-as.c index ce87653..ee9cd21 100644 --- a/envydis/core-as.c +++ b/envydis/core-as.c @@ -741,7 +741,7 @@ struct matches *do_as(const struct disisa *isa, struct varinfo *varinfo, struct struct iasctx c = { isa, varinfo }; struct iasctx *ctx = &c; convert_insn(ctx, insn); - struct matches *m = atomtab_a(ctx, isa->troot, 0); + struct matches *m = atomtab_a(ctx, isa->trootas ?: isa->troot, 0); int i; for (i = 0; i < m->mnum; i++) if (m->m[i].lpos == ctx->atomsnum) { diff --git a/envydis/core-dis.c b/envydis/core-dis.c index 9d9ca5b..f4af5f2 100644 --- a/envydis/core-dis.c +++ b/envydis/core-dis.c @@ -489,7 +489,10 @@ struct dis_res *do_dis(struct decoctx *deco, uint32_t cur) { } ctx->isa = deco->isa; ctx->varinfo = deco->varinfo; - atomtab_d (ctx, res->a, res->m, deco->isa->troot); + if (deco->isa->tsched && (cur*stride % deco->isa->schedpos) == 0) + atomtab_d (ctx, res->a, res->m, deco->isa->tsched); + else + atomtab_d (ctx, res->a, res->m, deco->isa->troot); res->oplen = ctx->oplen; if (res->oplen + cur > deco->codesz) res->status |= DIS_STATUS_EOF; diff --git a/envydis/gm107.c b/envydis/gm107.c index f322ded..6858b0c 100644 --- a/envydis/gm107.c +++ b/envydis/gm107.c @@ -1910,11 +1910,22 @@ static struct insn tabroot[] = { { 0x0400000000000000ull, 0xfc00000000000000ull, OP8B, T(pred), N( "lop32i"), T(0400_0), ON(57, x), ON(52, cc), REG_00, ON(55, inv), REG_08, ON(56, inv), U32_20 }, { 0x0200000000000000ull, 0xfe00000000000000ull, OP8B, T(pred), N( "lop3"), N("lut"), ON(56, x), ON(47, cc), REG_00, REG_08, C34_RZ_O14_20, REG_39, U08_48 }, { 0x0100000000000000ull, 0xfff0000000000000ull, OP8B, T(pred), N( "mov32i"), REG_00, U32_20, U04_12 }, - /*XXX: hw expects this data prior to every 3 insns, this is a compromise between printing most scheds, and not disasm'ing other unknowns as sched */ - { 0x0000000000000000ull, 0xf000000000000000ull, OP8B, N( "sched"), SCHED0, SCHED1, SCHED2 }, { 0, 0, OP8B, OOPS }, }; +static struct insn tabsched[] = { + { 0x0000000000000000ull, 0x8000000000000000ull, OP8B, N( "sched"), SCHED0, SCHED1, SCHED2 }, + { 0, 0, OP8B, OOPS }, +}; + +static struct insn tabrootas[] = { + /* HACK: envyas does not seem to properly interpret sched ops + * when the mask is set to what's in tabsched. + */ + { 0x0000000000000000ull, 0xf000000000000000ull, OP8B, N( "sched"), SCHED0, SCHED1, SCHED2 }, + { 0, 0, OP8B, T(root) }, +}; + static void gm107_prep(struct disisa *isa) { // no variants yet } @@ -1926,4 +1937,7 @@ struct disisa gm107_isa_s = { 1, .i_need_g80as_hack = 1, .prep = gm107_prep, + .trootas = tabrootas, + .tsched = tabsched, + .schedpos = 0x20, }; diff --git a/include/dis.h b/include/dis.h index 5565170..a2366b9 100644 --- a/include/dis.h +++ b/include/dis.h @@ -41,6 +41,9 @@ struct disisa { void (*prep)(struct disisa *); struct vardata *vardata; uint32_t (*getcbsz)(const struct disisa *isa, struct varinfo *varinfo); + struct insn *trootas; + struct insn *tsched; + int schedpos; }; struct label { -- 2.7.3