- #include <stdio.h>
- #include <inttypes.h>
- #include "pretty_print.h"
- const char *opcodes[256] = {
- "trap","fcmp","fun","feql","fadd","fix","fsub","fixu", /* 0x0# */
- "flot","flot","flotu","flotu","sflot","sflot","sflotu","sflotu",
- "fmul","fcmpe","fune","feqle","fdiv","fsqrt","frem","fint", /* 0x1# */
- "mul","mul","mulu","mulu","div","div","divu","divu",
- "add","add","addu","addu","sub","sub","subu","subu", /* 0x2# */
- "2addu","2addu","4addu","4addu","8addu","8addu","16addu","16addu",
- "cmp","cmp","cmpu","cmpu","neg","neg","negu","negu", /* 0x3# */
- "sl","sl","slu","slu","sr","sr","sru","sru",
- "bn","bn","bz","bz","bp","bp","bod","bod", /* 0x4# */
- "bnn","bnn","bnz","bnz","bnp","bnp","bev","bev",
- "pbn","pbn","pbz","pbz","pbp","pbp","pbod","pbod", /* 0x5# */
- "pbnn","pbnn","pbnz","pbnz","pbnp","pbnp","pbev","pbev",
- "csn","csn","csz","csz","csp","csp","csod","csod", /* 0x6# */
- "csnn","csnn","csnz","csnz","csnp","csnp","csev","csev",
- "zsn","zsn","zsz","zsz","zsp","zsp","zsod","zsod", /* 0x7# */
- "zsnn","zsnn","zsnz","zsnz","zsnp","zsnp","zsev","zsev",
- "ldb","ldb","ldbu","ldbu","ldw","ldw","ldwu","ldwu", /* 0x8# */
- "ldt","ldt","ldtu","ldtu","ldo","ldo","ldou","ldou",
- "ldsf","ldsf","ldht","ldht","cswap","cswap","ldunc","ldunc", /* 0x9# */
- "ldvts","ldvts","preld","preld","prego","prego","go","go",
- "stb","stb","stbu","stbu","stw","stw","stwu","stwu", /* 0xA# */
- "stt","stt","sttu","sttu","sto","sto","stou","stou",
- "stsf","stsf","stht","stht","stco","stco","stunc","stunc", /* 0xB# */
- "syncd","syncd","prest","prest","syncid","syncid","pushgo","pushgo",
- "or","or","orn","orn","nor","nor","xor","xor", /* 0xC# */
- "and","and","andn","andn","nand","nand","nxor","nxor",
- "bdif","bdif","wdif","wdif","tdif","tdif","odif","odif", /* 0xD# */
- "mux","mux","sadd","sadd","mor","mor","mxor","mxor",
- "seth","setmh","setml","setl","inch","incmh","incml","incl", /* 0xE# */
- "orh","ormh","orml","orl","andnh","andnmh","andnml","andnl",
- "jmp","jmp","pushj","pushj","geta","geta","put","put", /* 0xF# */
- "pop","resume","save","unsave","sync","swym","get","trip"
- };
- /* kinds of arguments and format strings
- * S#: register number, e.g. $123
- * #: 8-bit unsigned, e.g. #1F
- * ##: the same, 16 Bit, e.g. #1337
- * ###: the same, 24 Bit, e.g. #1F2E3D
- * F##: relative 16-bit adress, forwards, e.g.. @+4*#1234
- * B##: the same, backwards, z.B. @-4*#1234
- * F###, B###: the same, 24 Bit
- * R#: special register, z.B. rH
- * ROUND: rounding mode, string contains comma
- */
- enum op_type {
- OP_SX_SY_SZ,
- OP_SX_SY_Z,
- OP_SX_Y_SZ,
- OP_SX_Y_Z,
- OP_X_SY_SZ,
- OP_X_SY_Z,
- /* OP_X_Y_SZ, */
- /* OP_X_Y_Z, */
- OP_SX_YZ,
- OP_XYZ,
- #define IS_SIMPLE_ARGF(x) ((x) <= OP_XYZ)
- /* complicated argument formats */
- OP_SX_ROUND_SZ,
- OP_SX_ROUND_Z,
- OP_SX_FYZ,
- OP_SX_BYZ,
- OP_FXYZ,
- OP_BXYZ,
- OP_RX_SZ,
- OP_RX_Z,
- OP_SX,
- OP_SZ,
- OP_SX_RZ,
- /* failback mode, if illegal argument format. Never occurs in argformats */
- OP_SX_Z,
- OP_X_SZ,
- OP_X_Z
- };
- static const char *opfstrings[] = {
- [OP_SX_SY_SZ] = "$%hu,$%hu,$%hu\n",
- [OP_SX_SY_Z] = "$%hu,$%hu,#%02hx\n",
- [OP_SX_Y_SZ] = "$%hu,#%02hx,$%hu\n",
- [OP_SX_Y_Z] = "$%hu,#%02hx,#%02hx\n",
- [OP_X_SY_SZ] = "#%02hx,$%hu,$%hu\n",
- [OP_X_SY_Z] = "#%02hx,$%hu,#%02hx\n",
- /* [OP_X_Y_SZ] = "#%02hx,#%02hx,$%hu\n", */
- /* [OP_X_Y_Z] = "#%02hx,#%02hx,#%02hx\n", */
- [OP_SX_YZ] = "$%hu,#%02hx%02hx\n",
- [OP_XYZ] = "#%02hx%02hx%02hx\n",
- [OP_SX_ROUND_SZ] = "$%hu,%s$%hu\n",
- [OP_SX_ROUND_Z] = "$%hu,%s%02hx\n",
- /* x, abs(yz), absolute adress */
- [OP_SX_FYZ] = "$%hu,@+4*#%04" PRIx64 " <%016" PRIx64 ">\n",
- [OP_SX_BYZ] = "$%hu,@-4*#%04" PRIx64" <%016" PRIx64 ">\n",
- [OP_FXYZ] = "@+4*#%06" PRIx64" <%016" PRIx64 ">\n",
- [OP_BXYZ] = "@-4*#%06" PRIx64" <%016" PRIx64 ">\n",
- [OP_RX_SZ] = "%s,$%hu\n",
- [OP_RX_Z] = "%s,#%02hx\n",
- [OP_SX] = "$%hu\n",
- [OP_SZ] = "$%hu\n",
- [OP_SX_RZ] = "$%hu,%s\n",
- [OP_SX_Z] = "$%hu,#%02hx\n",
- [OP_X_SZ] = "#%02hx,$%hu\n",
- [OP_X_Z] = "#%02hx,%02hx\n"
- };
- /* helpful macros */
- #define OP_ROUND_PAIR OP_SX_ROUND_SZ, OP_SX_ROUND_Z,
- #define OP_STD_PAIR OP_SX_SY_SZ, OP_SX_SY_Z,
- #define OP_STD_ROW OP_STD_PAIR OP_STD_PAIR OP_STD_PAIR OP_STD_PAIR
- #define OP_BR_PAIR OP_SX_FYZ, OP_SX_BYZ,
- #define OP_BR_ROW OP_BR_PAIR OP_BR_PAIR OP_BR_PAIR OP_BR_PAIR
- #define OP_SX_YZ_ROW OP_SX_YZ, OP_SX_YZ, OP_SX_YZ, OP_SX_YZ, \
- OP_SX_YZ, OP_SX_YZ, OP_SX_YZ, OP_SX_YZ,
- /* argument formats to the opcodes, grouped by 32 opcodes */
- static const unsigned char argformats[256] = {
- /* trap */ OP_XYZ,
- /* fcmp */ OP_SX_SY_SZ,
- /* fun */ OP_SX_SY_SZ,
- /* feql */ OP_SX_SY_SZ,
- /* fadd */ OP_SX_SY_SZ,
- /* fix */ OP_SX_ROUND_SZ,
- /* fsub */ OP_SX_SY_SZ,
- /* fixu */ OP_SX_ROUND_SZ,
- /* flot */ OP_ROUND_PAIR
- /* flotu */ OP_ROUND_PAIR
- /* sflot */ OP_ROUND_PAIR
- /* sflotu */ OP_ROUND_PAIR
- /* fmul */ OP_SX_SY_SZ,
- /* fcmpe */ OP_SX_SY_SZ,
- /* fune */ OP_SX_SY_SZ,
- /* feqle */ OP_SX_SY_SZ,
- /* fdiv */ OP_SX_SY_SZ,
- /* fsqrt */ OP_SX_ROUND_SZ,
- /* frem */ OP_SX_SY_SZ,
- /* fint */ OP_SX_ROUND_SZ,
- /* mul - divu */ OP_STD_ROW
- /* add - 16addu */ OP_STD_ROW OP_STD_ROW
- /* cmp */ OP_STD_PAIR
- /* cmpu */ OP_STD_PAIR
- /* neg */ OP_SX_Y_SZ, OP_SX_Y_Z,
- /* negu */ OP_SX_Y_SZ, OP_SX_Y_Z,
- /* sl - sru */ OP_STD_ROW
- /* bn - bev */ OP_BR_ROW OP_BR_ROW
- /* pbn - pbev */ OP_BR_ROW OP_BR_ROW
- /* csn - csev */ OP_STD_ROW OP_STD_ROW
- /* zsn - zsev */ OP_STD_ROW OP_STD_ROW
- /* ldb - ldou */ OP_STD_ROW OP_STD_ROW
- /* ldsf - go */ OP_STD_ROW OP_STD_ROW
- /* stb - stou */ OP_STD_ROW OP_STD_ROW
- /* stsf */ OP_STD_PAIR
- /* stht */ OP_STD_PAIR
- /* stco */ OP_X_SY_SZ, OP_X_SY_Z,
- /* stunc */ OP_STD_PAIR
- /* syncd - pushgo */ OP_STD_ROW
- /* or - nxor */ OP_STD_ROW OP_STD_ROW
- /* bdif - mxor */ OP_STD_ROW OP_STD_ROW
- /* seth - andnl */ OP_SX_YZ_ROW OP_SX_YZ_ROW
- /* jmp */ OP_FXYZ, OP_BXYZ,
- /* pushj */ OP_BR_PAIR
- /* geta */ OP_BR_PAIR
- /* put */ OP_RX_SZ, OP_RX_Z,
- /* pop */ OP_SX_YZ,
- /* resume */ OP_XYZ,
- /* save */ OP_SX,
- /* unsave */ OP_SZ,
- /* sync */ OP_XYZ,
- /* swym */ OP_XYZ,
- /* get */ OP_SX_RZ,
- /* trip */ OP_XYZ
- };
- const char *special_regs[NUM_SPECIAL_REGS] = {
- "rB","rD","rE","rH","rJ","rM","rR","rBB",
- "rC","rN","rO","rS","rI","rT","rTT","rK",
- "rQ","rU","rV","rG","rL","rA","rF","rP",
- "rW","rX","rY","rZ","rWW","rXX","rYY","rZZ"
- };
- const char *rounding_modes[NUM_ROUNDING_MODES] = {
- ",",
- "ROUND_OFF,",
- "ROUND_UP,",
- "ROUND_DOWN,",
- "ROUND_NEAR,"
- };
- extern void printOp(const char *buffer,uint64_t address) {
- unsigned char opcode = buffer[0],
- x = buffer[1],
- y = buffer[2],
- z = buffer[3],
- argf = argformats[opcode];
- int64_t offset;
- printf("#%016" PRIx64 " %02hx%02hx%02hx%02hx %-6s ",
- address,opcode,x,y,z,opcodes[opcode]);
- if (IS_SIMPLE_ARGF(argf))
- printf(opfstrings[argf],x,y,z);
- else switch (argf) {
- case OP_SX_ROUND_SZ:
- case OP_SX_ROUND_Z:
- if (y >= NUM_ROUNDING_MODES) {
- argf = argf == OP_SX_ROUND_SZ ? OP_SX_Y_SZ : OP_SX_Y_Z;
- printf(opfstrings[argf],x,y,z);
- } else
- printf(opfstrings[argf],x,rounding_modes[y],z);
- break;
- case OP_SX:
- case OP_SZ: printf(opfstrings[argf],(argf == OP_SX ? x : z)); break;
- case OP_SX_RZ:
- if (z >= NUM_SPECIAL_REGS) printf(opfstrings[OP_SX_Z],x,z);
- else printf(opfstrings[argf],x,special_regs[z]); break;
- case OP_RX_SZ:
- case OP_RX_Z:
- if (x >= NUM_SPECIAL_REGS)
- printf(opfstrings[argf == OP_RX_Z ? OP_X_Z : OP_X_SZ],x,z);
- else
- printf(opfstrings[argf],special_regs[x],z);
- break;
- case OP_SX_FYZ:
- case OP_SX_BYZ:
- offset = (y << 8) + z;
- offset = argf == OP_SX_FYZ ? offset : (1 << 16) - offset;
- printf(opfstrings[argf],x,
- (uint64_t)offset < 0 ? -offset : offset,
- address + 4*offset);
- break;
- case OP_FXYZ:
- case OP_BXYZ:
- offset = (x << 16) + (y << 8) + z;
- offset = argf == OP_FXYZ ? offset : (1 << 24) - offset;
- printf(opfstrings[argf],
- (uint64_t)offset < 0 ? -offset : offset,
- address + 4*offset);
- break;
- }
- }
- extern void printCode(const char* buffer, size_t count,uint64_t address) {
- while(count > 4) {
- printOp(buffer,address);
- buffer += 4;
- address += 4;
- count -= 4;
- }
- }