Skip to content

Instantly share code, notes, and snippets.

@exjam
Last active August 29, 2015 14:25
Show Gist options
  • Save exjam/d4b596605f56ea1bc075 to your computer and use it in GitHub Desktop.
Save exjam/d4b596605f56ea1bc075 to your computer and use it in GitHub Desktop.
#include <cassert>
#include <fstream>
#include <cstdint>
#include <string>
#include <vector>
#include <iostream>
#include "r600_opcodes.h"
#include "bigendianview.h"
namespace gsh
{
struct Header
{
static const uint32_t Magic = 0x47667832;
uint32_t magic;
uint32_t unk1;
uint32_t unk2;
uint32_t unk3;
uint32_t unk4;
uint32_t unk5;
uint32_t unk6;
uint32_t unk7;
};
struct Block
{
enum BlockType : uint32_t
{
VertexShader = 5,
PixelShader = 6
};
static const uint32_t Magic = 0x424c4b7b;
uint32_t magic;
uint32_t unk1;
uint32_t unk2;
uint32_t unk3;
uint32_t type;
uint32_t dataLength;
uint32_t unk4;
uint32_t unk5;
char *data;
};
}
void parseALU(r600::alu::Instruction *code, size_t count)
{
for (auto i = 0u; i < count; ++i) {
auto ins = code[i];
if (ins.word1.encoding == 0) {
std::cout
<< " AluOp2: " << ins.op2.inst
<< " remap: " << r600::alu::op2map[ins.op2.inst]
<< " name: " << r600::alu::op2name[r600::alu::op2map[ins.op2.inst]]
<< std::endl;
} else {
std::cout
<< " AluOp3: " << ins.op3.inst
<< " remap: " << r600::alu::op3map[ins.op3.inst]
<< " name: " << r600::alu::op3name[r600::alu::op2map[ins.op3.inst]]
<< std::endl;
}
}
}
void parseVertexShader(r600::cf::Instruction *code, size_t count)
{
for (auto i = 0u; i < count; ++i) {
auto ins = code[i];
switch (static_cast<r600::cf::Type>(ins.type)) {
case r600::cf::Type::Normal:
std::cout
<< "CfNormal: " << ins.word1.inst
<< " mapped: " << r600::cf::map[ins.word1.inst]
<< " name: " << r600::cf::name[r600::cf::map[ins.word1.inst]]
<< std::endl;
break;
case r600::cf::Type::Export:
std::cout
<< "CfExport: " << ins.word1.inst
<< " mapped: " << r600::exp::map[ins.word1.inst]
<< " name: " << r600::exp::name[r600::exp::map[ins.word1.inst]]
<< std::endl;
break;
case r600::cf::Type::Alu:
case r600::cf::Type::AluExtended:
std::cout
<< "CfAlu: " << ins.aluWord1.inst
<< " mapped: " << r600::alu::map[ins.aluWord1.inst]
<< " name: " << r600::alu::name[r600::alu::map[ins.aluWord1.inst]]
<< " addr: " << ins.aluWord0.addr
<< " count: " << ins.aluWord1.count
<< std::endl;
parseALU(reinterpret_cast<r600::alu::Instruction*>(code + ins.aluWord0.addr), ins.aluWord1.count);
break;
}
if (ins.word1.endOfProgram) {
std::cout << "End of Program" << std::endl;
break;
}
}
}
bool parseGSH(BigEndianView &fh)
{
gsh::Header header;
fh.read(header.magic);
if (header.magic != gsh::Header::Magic) {
std::cout << "Unexpected gsh magic " << header.magic << std::endl;
return false;
}
fh.read(header.unk1);
fh.read(header.unk2);
fh.read(header.unk3);
fh.read(header.unk4);
fh.read(header.unk5);
fh.read(header.unk6);
fh.read(header.unk7);
while (!fh.eof()) {
gsh::Block block;
fh.read(block.magic);
if (block.magic != gsh::Block::Magic) {
std::cout << "Unexpected block magic " << header.magic << std::endl;
return false;
}
fh.read(block.unk1);
fh.read(block.unk2);
fh.read(block.unk3);
fh.read(block.type);
fh.read(block.dataLength);
fh.read(block.unk4);
fh.read(block.unk5);
block.data = fh.readRaw<char>(block.dataLength);
if (block.type == gsh::Block::VertexShader) {
assert((block.dataLength % 4) == 0);
parseVertexShader(reinterpret_cast<r600::cf::Instruction*>(block.data), block.dataLength / 4);
}
}
}
int main(int argc, char **argv)
{
// Read whole file
std::vector<char> data;
std::ifstream file(argv[1], std::ifstream::binary | std::ifstream::in);
file.seekg(0, std::ifstream::end);
auto size = static_cast<size_t>(file.tellg());
file.seekg(0, std::ifstream::beg);
data.resize(size);
file.read(data.data(), size);
file.close();
// Parse
BigEndianView fh { data.data(), data.size() };
return parseGSH(fh) ? 0 : -1;
}
#pragma once
#include <cstdint>
#include <vector>
#include <map>
namespace r600
{
namespace cf
{
enum class Type : uint32_t
{
Normal = 0,
Export = 1,
Alu = 2,
AluExtended = 3
};
struct Word0
{
uint32_t addr;
};
struct Word1
{
uint32_t popCount : 3;
uint32_t cfConst : 5;
uint32_t cond : 2;
uint32_t count : 3;
uint32_t callCount : 6;
uint32_t : 2;
uint32_t endOfProgram : 1;
uint32_t validPixelMode : 1;
uint32_t inst : 7;
uint32_t wholeQuadMode : 1;
uint32_t barrier : 1;
};
struct AluWord0
{
uint32_t addr : 16;
uint32_t kcacheBank0 : 4;
uint32_t kcacheBank1 : 2;
uint32_t kcacheMode0 : 4;
};
struct AluWord1
{
uint32_t kcacheMode1 : 2;
uint32_t kcacheAddr0 : 8;
uint32_t kcacheAddr1 : 8;
uint32_t count : 7;
uint32_t altConst : 1;
uint32_t inst : 4;
uint32_t wholeQuadMode : 1;
uint32_t barrier : 1;
};
union Instruction
{
struct
{
uint32_t : 32;
uint32_t : 28;
Type type : 2;
uint32_t : 2;
};
struct
{
Word0 word0;
Word1 word1;
};
struct
{
AluWord0 aluWord0;
AluWord1 aluWord1;
};
};
enum class inst : uint32_t
{
#define CF_INST(name, value) name = value,
#include "r600_opcodes_def.inl"
#undef CF_INST
};
extern std::map<uint32_t, const char *> name;
extern std::vector<uint32_t> map;
} // namespace cf
namespace exp
{
enum class inst : uint32_t
{
#define EXP_INST(name, value) name = value,
#include "r600_opcodes_def.inl"
#undef EXP_INST
};
extern std::map<uint32_t, const char *> name;
extern std::vector<uint32_t> map;
} // namespace exp
namespace alu
{
struct Word0
{
uint32_t src0Sel : 9;
uint32_t src0Rel : 1;
uint32_t src0Chan : 2;
uint32_t src0Neg : 1;
uint32_t src1Sel : 9;
uint32_t src1Rel : 1;
uint32_t src1Chan : 2;
uint32_t src1Neg : 1;
uint32_t indexMode : 3;
uint32_t predSel : 2;
uint32_t last : 1;
};
struct Word1
{
uint32_t : 15;
uint32_t encoding : 3;
uint32_t bankSwizzle : 3;
uint32_t dstGpr : 7;
uint32_t dstRel : 1;
uint32_t dstChan : 2;
uint32_t clamp : 1;
};
struct Word1Op2
{
uint32_t src0Abs : 1;
uint32_t src1Abs : 1;
uint32_t updateExecuteMask : 1;
uint32_t updatePred : 1;
uint32_t writeMask : 1;
uint32_t omod : 2;
uint32_t inst : 11;
uint32_t : 14;
};
struct Word1Op3
{
uint32_t src2Sel : 9;
uint32_t src2Rel : 1;
uint32_t src2Chan : 2;
uint32_t src2Neg : 1;
uint32_t inst : 5;
uint32_t : 14;
};
struct Instruction
{
Word0 word0;
union
{
Word1 word1;
Word1Op2 op2;
Word1Op3 op3;
};
};
enum class inst : uint32_t
{
#define ALU_INST(name, value) name = value,
#include "r600_opcodes_def.inl"
#undef ALU_INST
};
enum class op2 : uint32_t
{
#define ALU_OP2(name, value) name = value,
#include "r600_opcodes_def.inl"
#undef ALU_OP2
};
enum class op3 : uint32_t
{
#define ALU_OP3(name, value) name = value,
#include "r600_opcodes_def.inl"
#undef ALU_OP3
};
extern std::map<uint32_t, const char *> name;
extern std::vector<uint32_t> map;
extern std::map<uint32_t, const char *> op2name;
extern std::vector<uint32_t> op2map;
extern std::map<uint32_t, const char *> op3name;
extern std::vector<uint32_t> op3map;
} // namespace alu
} // namespace r600
#ifndef CF_INST
#define CF_INST(name, value)
#endif
#ifndef EXP_INST
#define EXP_INST(name, value)
#endif
#ifndef ALU_INST
#define ALU_INST(name, value)
#endif
#ifndef ALU_OP2
#define ALU_OP2(name, value)
#endif
#ifndef ALU_OP3
#define ALU_OP3(name, value)
#endif
CF_INST(NOP, 0x00000000)
CF_INST(TEX, 0x00000001)
CF_INST(VTX, 0x00000002)
CF_INST(VTX_TC, 0x00000003)
CF_INST(LOOP_START, 0x00000004)
CF_INST(LOOP_END, 0x00000005)
CF_INST(LOOP_START_DX10, 0x00000006)
CF_INST(LOOP_START_NO_AL, 0x00000007)
CF_INST(LOOP_CONTINUE, 0x00000008)
CF_INST(LOOP_BREAK, 0x00000009)
CF_INST(JUMP, 0x0000000A)
CF_INST(PUSH, 0x0000000B)
CF_INST(PUSH_ELSE, 0x0000000C)
CF_INST(ELSE, 0x0000000D)
CF_INST(POP, 0x0000000E)
CF_INST(POP_JUMP, 0x0000000F)
CF_INST(POP_PUSH, 0x00000010)
CF_INST(POP_PUSH_ELSE, 0x00000011)
CF_INST(CALL, 0x00000012)
CF_INST(CALL_FS, 0x00000013)
CF_INST(RETURN, 0x00000014)
CF_INST(EMIT_VERTEX, 0x00000015)
CF_INST(EMIT_CUT_VERTEX, 0x00000016)
CF_INST(CUT_VERTEX, 0x00000017)
CF_INST(KILL, 0x00000018)
CF_INST(END_PROGRAM, 0x00000019)
CF_INST(WAIT_ACK, 0x0000001A)
CF_INST(TEX_ACK, 0x0000001B)
CF_INST(VTX_ACK, 0x0000001C)
CF_INST(VTX_TC_ACK, 0x0000001D)
EXP_INST(MEM_STREAM0, 0x00000020)
EXP_INST(MEM_STREAM1, 0x00000021)
EXP_INST(MEM_STREAM2, 0x00000022)
EXP_INST(MEM_STREAM3, 0x00000023)
EXP_INST(MEM_SCRATCH, 0x00000024)
EXP_INST(MEM_REDUCTION, 0x00000025)
EXP_INST(MEM_RING, 0x00000026)
EXP_INST(EXP, 0x00000027)
EXP_INST(EXP_DONE, 0x00000028)
EXP_INST(MEM_EXPORT, 0x0000003A)
ALU_INST(ALU, 0x00000008)
ALU_INST(ALU_PUSH_BEFORE, 0x00000009)
ALU_INST(ALU_POP_AFTER, 0x0000000A)
ALU_INST(ALU_POP2_AFTER, 0x0000000B)
ALU_INST(ALU_EXT, 0x0000000C)
ALU_INST(ALU_CONTINUE, 0x0000000D)
ALU_INST(ALU_BREAK, 0x0000000E)
ALU_INST(ALU_ELSE_AFTER, 0x0000000F)
ALU_OP2(ADD, 0x00000000)
ALU_OP2(MUL, 0x00000001)
ALU_OP2(MUL_IEEE, 0x00000002)
ALU_OP2(MAX, 0x00000003)
ALU_OP2(MIN, 0x00000004)
ALU_OP2(MAX_DX10, 0x00000005)
ALU_OP2(MIN_DX10, 0x00000006)
ALU_OP2(FREXP_64, 0x00000007)
ALU_OP2(SETE, 0x00000008)
ALU_OP2(SETGT, 0x00000009)
ALU_OP2(SETGE, 0x0000000A)
ALU_OP2(SETNE, 0x0000000B)
ALU_OP2(SETE_DX10, 0x0000000C)
ALU_OP2(SETGT_DX10, 0x0000000D)
ALU_OP2(SETGE_DX10, 0x0000000E)
ALU_OP2(SETNE_DX10, 0x0000000F)
ALU_OP2(FRACT, 0x00000010)
ALU_OP2(TRUNC, 0x00000011)
ALU_OP2(CEIL, 0x00000012)
ALU_OP2(RNDNE, 0x00000013)
ALU_OP2(FLOOR, 0x00000014)
ALU_OP2(MOVA, 0x00000015)
ALU_OP2(MOVA_FLOOR, 0x00000016)
ALU_OP2(ADD_64, 0x00000017)
ALU_OP2(MOVA_INT, 0x00000018)
ALU_OP2(MOV, 0x00000019)
ALU_OP2(NOP, 0x0000001A)
ALU_OP2(MUL_64, 0x0000001B)
ALU_OP2(FLT64_TO_FLT32, 0x0000001C)
ALU_OP2(FLT32_TO_FLT64, 0x0000001D)
ALU_OP2(PRED_SETGT_UINT, 0x0000001E)
ALU_OP2(PRED_SETGE_UINT, 0x0000001F)
ALU_OP2(PRED_SETE, 0x00000020)
ALU_OP2(PRED_SETGT, 0x00000021)
ALU_OP2(PRED_SETGE, 0x00000022)
ALU_OP2(PRED_SETNE, 0x00000023)
ALU_OP2(PRED_SET_INV, 0x00000024)
ALU_OP2(PRED_SET_POP, 0x00000025)
ALU_OP2(PRED_SET_CLR, 0x00000026)
ALU_OP2(PRED_SET_RESTORE, 0x00000027)
ALU_OP2(PRED_SETE_PUSH, 0x00000028)
ALU_OP2(PRED_SETGT_PUSH, 0x00000029)
ALU_OP2(PRED_SETGE_PUSH, 0x0000002A)
ALU_OP2(PRED_SETNE_PUSH, 0x0000002B)
ALU_OP2(KILLE, 0x0000002C)
ALU_OP2(KILLGT, 0x0000002D)
ALU_OP2(KILLGE, 0x0000002E)
ALU_OP2(KILLNE, 0x0000002F)
ALU_OP2(AND_INT, 0x00000030)
ALU_OP2(OR_INT, 0x00000031)
ALU_OP2(XOR_INT, 0x00000032)
ALU_OP2(NOT_INT, 0x00000033)
ALU_OP2(ADD_INT, 0x00000034)
ALU_OP2(SUB_INT, 0x00000035)
ALU_OP2(MAX_INT, 0x00000036)
ALU_OP2(MIN_INT, 0x00000037)
ALU_OP2(MAX_UINT, 0x00000038)
ALU_OP2(MIN_UINT, 0x00000039)
ALU_OP2(SETE_INT, 0x0000003A)
ALU_OP2(SETGT_INT, 0x0000003B)
ALU_OP2(SETGE_INT, 0x0000003C)
ALU_OP2(SETNE_INT, 0x0000003D)
ALU_OP2(SETGT_UINT, 0x0000003E)
ALU_OP2(SETGE_UINT, 0x0000003F)
ALU_OP2(KILLGT_UINT, 0x00000040)
ALU_OP2(KILLGE_UINT, 0x00000041)
ALU_OP2(PRED_SETE_INT, 0x00000042)
ALU_OP2(PRED_SETGT_INT, 0x00000043)
ALU_OP2(PRED_SETGE_INT, 0x00000044)
ALU_OP2(PRED_SETNE_INT, 0x00000045)
ALU_OP2(KILLE_INT, 0x00000046)
ALU_OP2(KILLGT_INT, 0x00000047)
ALU_OP2(KILLGE_INT, 0x00000048)
ALU_OP2(KILLNE_INT, 0x00000049)
ALU_OP2(PRED_SETE_PUSH_INT, 0x0000004A)
ALU_OP2(PRED_SETGT_PUSH_INT, 0x0000004B)
ALU_OP2(PRED_SETGE_PUSH_INT, 0x0000004C)
ALU_OP2(PRED_SETNE_PUSH_INT, 0x0000004D)
ALU_OP2(PRED_SETLT_PUSH_INT, 0x0000004E)
ALU_OP2(PRED_SETLE_PUSH_INT, 0x0000004F)
ALU_OP2(DOT4, 0x00000050)
ALU_OP2(DOT4_IEEE, 0x00000051)
ALU_OP2(CUBE, 0x00000052)
ALU_OP2(MAX4, 0x00000053)
ALU_OP2(GROUP_BARRIER, 0x00000054)
ALU_OP2(GROUP_SEQ_BEGIN, 0x00000055)
ALU_OP2(GROUP_SEQ_END, 0x00000056)
ALU_OP2(SET_MODE, 0x00000057)
ALU_OP2(SET_CF_IDX0, 0x00000058)
ALU_OP2(SET_CF_IDX1, 0x00000059)
ALU_OP2(SET_LDS_SIZE, 0x0000005A)
ALU_OP2(MUL_INT24, 0x0000005B)
ALU_OP2(MULHI_INT24, 0x0000005C)
ALU_OP2(MOVA_GPR_INT, 0x00000060)
ALU_OP2(EXP_IEEE, 0x00000061)
ALU_OP2(LOG_CLAMPED, 0x00000062)
ALU_OP2(LOG_IEEE, 0x00000063)
ALU_OP2(RECIP_CLAMPED, 0x00000064)
ALU_OP2(RECIP_FF, 0x00000065)
ALU_OP2(RECIP_IEEE, 0x00000066)
ALU_OP2(RECIPSQRT_CLAMPED, 0x00000067)
ALU_OP2(RECIPSQRT_FF, 0x00000068)
ALU_OP2(RECIPSQRT_IEEE, 0x00000069)
ALU_OP2(SQRT_IEEE, 0x0000006A)
ALU_OP2(FLT_TO_INT, 0x0000006B)
ALU_OP2(INT_TO_FLT, 0x0000006C)
ALU_OP2(UINT_TO_FLT, 0x0000006D)
ALU_OP2(SIN, 0x0000006E)
ALU_OP2(COS, 0x0000006F)
ALU_OP2(ASHR_INT, 0x00000070)
ALU_OP2(LSHR_INT, 0x00000071)
ALU_OP2(LSHL_INT, 0x00000072)
ALU_OP2(MULLO_INT, 0x00000073)
ALU_OP2(MULHI_INT, 0x00000074)
ALU_OP2(MULLO_UINT, 0x00000075)
ALU_OP2(MULHI_UINT, 0x00000076)
ALU_OP2(RECIP_INT, 0x00000077)
ALU_OP2(RECIP_UINT, 0x00000078)
ALU_OP2(FLT_TO_UINT, 0x00000079)
ALU_OP2(LDEXP_64, 0x0000007A)
ALU_OP2(FRACT_64, 0x0000007B)
ALU_OP2(PRED_SETGT_64, 0x0000007C)
ALU_OP2(PRED_SETE_64, 0x0000007D)
ALU_OP2(PRED_SETGE_64, 0x0000007E)
ALU_OP3(BFE_UINT, 0x00000004)
ALU_OP3(BFE_INT, 0x00000005)
ALU_OP3(BFI_INT, 0x00000006)
ALU_OP3(FMA, 0x00000007)
ALU_OP3(MULADD_64, 0x00000008)
ALU_OP3(MULADD_64_M2, 0x00000009)
ALU_OP3(MULADD_64_M4, 0x0000000A)
ALU_OP3(MULADD_64_D2, 0x0000000B)
ALU_OP3(MUL_LIT, 0x0000000C)
ALU_OP3(MUL_LIT_M2, 0x0000000D)
ALU_OP3(MUL_LIT_M4, 0x0000000E)
ALU_OP3(MUL_LIT_D2, 0x0000000F)
ALU_OP3(MULADD, 0x00000010)
ALU_OP3(MULADD_M2, 0x00000011)
ALU_OP3(MULADD_M4, 0x00000012)
ALU_OP3(MULADD_D2, 0x00000013)
ALU_OP3(MULADD_IEEE, 0x00000014)
ALU_OP3(MULADD_IEEE_M2, 0x00000015)
ALU_OP3(MULADD_IEEE_M4, 0x00000016)
ALU_OP3(MULADD_IEEE_D2, 0x00000017)
ALU_OP3(CNDE, 0x00000018)
ALU_OP3(CNDGT, 0x00000019)
ALU_OP3(CNDGE, 0x0000001A)
ALU_OP3(CNDE_INT, 0x0000001C)
ALU_OP3(CNDGT_INT, 0x0000001D)
ALU_OP3(CNDGE_INT, 0x0000001E)
#undef CF_INST
#undef EXP_INST
#undef ALU_INST
#undef ALU_OP2
#undef ALU_OP3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment