Last active
August 29, 2015 14:25
-
-
Save exjam/d4b596605f56ea1bc075 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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