| 1 | // |
| 2 | // Jaguar RISC Disassembly |
| 3 | // |
| 4 | // Originally by David Raingeard |
| 5 | // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Carwin Jones (BeOS) |
| 6 | // Minor cleanups by James Hammons |
| 7 | // (C) 2012 Underground Software |
| 8 | // |
| 9 | // JLH = James Hammons <jlhamm@acm.org> |
| 10 | // |
| 11 | // Who When What |
| 12 | // --- ---------- ------------------------------------------------------------- |
| 13 | // JLH 06/01/2012 Created this log (long overdue! ;-) |
| 14 | // JLH 01/23/2013 Beautifying of disassembly, including hex digits of opcodes |
| 15 | // and operands |
| 16 | // |
| 17 | |
| 18 | #include "jagdasm.h" |
| 19 | |
| 20 | #include <stdio.h> |
| 21 | #include "jaguar.h" |
| 22 | |
| 23 | #define ROPCODE(a) JaguarReadWord(a) |
| 24 | |
| 25 | uint8_t convert_zero[32] = |
| 26 | { 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 }; |
| 27 | |
| 28 | const char * condition[32] = |
| 29 | { |
| 30 | "", |
| 31 | "nz,", |
| 32 | "z,", |
| 33 | "???,", |
| 34 | "nc,", |
| 35 | "nc nz,", |
| 36 | "nc z,", |
| 37 | "???,", |
| 38 | |
| 39 | "c,", |
| 40 | "c nz,", |
| 41 | "c z,", |
| 42 | "???,", |
| 43 | "???,", |
| 44 | "???,", |
| 45 | "???,", |
| 46 | "???,", |
| 47 | |
| 48 | "???,", |
| 49 | "???,", |
| 50 | "???,", |
| 51 | "???,", |
| 52 | "nn,", |
| 53 | "nn nz,", |
| 54 | "nn z,", |
| 55 | "???,", |
| 56 | |
| 57 | "n,", |
| 58 | "n nz,", |
| 59 | "n z,", |
| 60 | "???,", |
| 61 | "???,", |
| 62 | "???,", |
| 63 | "???,", |
| 64 | "never," |
| 65 | }; |
| 66 | |
| 67 | |
| 68 | |
| 69 | char * signed_16bit(int16_t val) |
| 70 | { |
| 71 | static char temp[10]; |
| 72 | |
| 73 | if (val < 0) |
| 74 | sprintf(temp, "-$%X", -val); |
| 75 | else |
| 76 | sprintf(temp, "$%X", val); |
| 77 | |
| 78 | return temp; |
| 79 | } |
| 80 | |
| 81 | |
| 82 | unsigned dasmjag(int dsp_type, char * bufferOut, unsigned pc) |
| 83 | { |
| 84 | char buffer[64]; |
| 85 | int op = ROPCODE(pc); |
| 86 | int reg1 = (op >> 5) & 31; |
| 87 | int reg2 = op & 31; |
| 88 | int size = 2; |
| 89 | pc += 2; |
| 90 | |
| 91 | switch (op >> 10) |
| 92 | { |
| 93 | case 0: sprintf(buffer, "ADD R%02d,R%02d", reg1, reg2); break; |
| 94 | case 1: sprintf(buffer, "ADDC R%02d,R%02d", reg1, reg2); break; |
| 95 | case 2: sprintf(buffer, "ADDQ $%X,R%02d", convert_zero[reg1], reg2); break; |
| 96 | case 3: sprintf(buffer, "ADDQT $%X,R%02d", convert_zero[reg1], reg2); break; |
| 97 | case 4: sprintf(buffer, "SUB R%02d,R%02d", reg1, reg2); break; |
| 98 | case 5: sprintf(buffer, "SUBC R%02d,R%02d", reg1, reg2); break; |
| 99 | case 6: sprintf(buffer, "SUBQ $%X,R%02d", convert_zero[reg1], reg2); break; |
| 100 | case 7: sprintf(buffer, "SUBQT $%X,R%02d", convert_zero[reg1], reg2); break; |
| 101 | case 8: sprintf(buffer, "NEG R%02d", reg2); break; |
| 102 | case 9: sprintf(buffer, "AND R%02d,R%02d", reg1, reg2); break; |
| 103 | case 10: sprintf(buffer, "OR R%02d,R%02d", reg1, reg2); break; |
| 104 | case 11: sprintf(buffer, "XOR R%02d,R%02d", reg1, reg2); break; |
| 105 | case 12: sprintf(buffer, "NOT R%02d", reg2); break; |
| 106 | case 13: sprintf(buffer, "BTST $%X,R%02d", reg1, reg2); break; |
| 107 | case 14: sprintf(buffer, "BSET $%X,R%02d", reg1, reg2); break; |
| 108 | case 15: sprintf(buffer, "BCLR $%X,R%02d", reg1, reg2); break; |
| 109 | case 16: sprintf(buffer, "MULT R%02d,R%02d", reg1, reg2); break; |
| 110 | case 17: sprintf(buffer, "IMULT R%02d,R%02d", reg1, reg2); break; |
| 111 | case 18: sprintf(buffer, "IMULTN R%02d,R%02d", reg1, reg2); break; |
| 112 | case 19: sprintf(buffer, "RESMAC R%02d", reg2); break; |
| 113 | case 20: sprintf(buffer, "IMACN R%02d,R%02d", reg1, reg2); break; |
| 114 | case 21: sprintf(buffer, "DIV R%02d,R%02d", reg1, reg2); break; |
| 115 | case 22: sprintf(buffer, "ABS R%02d", reg2); break; |
| 116 | case 23: sprintf(buffer, "SH R%02d,R%02d", reg1, reg2); break; |
| 117 | case 24: sprintf(buffer, "SHLQ $%X,R%02d", 32 - reg1, reg2); break; |
| 118 | case 25: sprintf(buffer, "SHRQ $%X,R%02d", convert_zero[reg1], reg2); break; |
| 119 | case 26: sprintf(buffer, "SHA R%02d,R%02d", reg1, reg2); break; |
| 120 | case 27: sprintf(buffer, "SHARQ $%X,R%02d", convert_zero[reg1], reg2); break; |
| 121 | case 28: sprintf(buffer, "ROR R%02d,R%02d", reg1, reg2); break; |
| 122 | case 29: sprintf(buffer, "RORQ $%X,R%02d", convert_zero[reg1], reg2); break; |
| 123 | case 30: sprintf(buffer, "CMP R%02d,R%02d", reg1, reg2); break; |
| 124 | case 31: sprintf(buffer, "CMPQ %s,R%02d", signed_16bit((int16_t)(reg1 << 11) >> 11), reg2);break; |
| 125 | case 32: if (dsp_type == JAGUAR_GPU) |
| 126 | sprintf(buffer, "SAT8 R%02d", reg2); |
| 127 | else |
| 128 | sprintf(buffer, "SUBQMOD $%X,R%02d", convert_zero[reg1], reg2); |
| 129 | break; |
| 130 | case 33: if (dsp_type == JAGUAR_GPU) |
| 131 | sprintf(buffer, "SAT16 R%02d", reg2); |
| 132 | else |
| 133 | sprintf(buffer, "SAT16S R%02d", reg2); |
| 134 | break; |
| 135 | case 34: sprintf(buffer, "MOVE R%02d,R%02d", reg1, reg2); break; |
| 136 | case 35: sprintf(buffer, "MOVEQ %d,R%02d", reg1, reg2); break; |
| 137 | case 36: sprintf(buffer, "MOVETA R%02d,R%02d", reg1, reg2); break; |
| 138 | case 37: sprintf(buffer, "MOVEFA R%02d,R%02d", reg1, reg2); break; |
| 139 | case 38: sprintf(buffer, "MOVEI #$%X,R%02d", ROPCODE(pc) | (ROPCODE(pc+2)<<16), reg2); size = 6; break; |
| 140 | case 39: sprintf(buffer, "LOADB (R%02d),R%02d", reg1, reg2); break; |
| 141 | case 40: sprintf(buffer, "LOADW (R%02d),R%02d", reg1, reg2); break; |
| 142 | case 41: sprintf(buffer, "LOAD (R%02d),R%02d", reg1, reg2); break; |
| 143 | case 42: if (dsp_type == JAGUAR_GPU) |
| 144 | sprintf(buffer, "LOADP (R%02d),R%02d", reg1, reg2); |
| 145 | else |
| 146 | sprintf(buffer, "SAT32S R%02d", reg2); |
| 147 | break; |
| 148 | case 43: sprintf(buffer, "LOAD (R14+$%X),R%02d", convert_zero[reg1]*4, reg2);break; |
| 149 | case 44: sprintf(buffer, "LOAD (R15+$%X),R%02d", convert_zero[reg1]*4, reg2);break; |
| 150 | case 45: sprintf(buffer, "STOREB R%02d,(R%02d)", reg2, reg1); break; |
| 151 | case 46: sprintf(buffer, "STOREW R%02d,(R%02d)", reg2, reg1); break; |
| 152 | case 47: sprintf(buffer, "STORE R%02d,(R%02d)", reg2, reg1); break; |
| 153 | case 48: if (dsp_type == JAGUAR_GPU) |
| 154 | sprintf(buffer, "STOREP R%02d,(R%02d)", reg2, reg1); |
| 155 | else |
| 156 | sprintf(buffer, "MIRROR R%02d", reg2); |
| 157 | break; |
| 158 | case 49: sprintf(buffer, "STORE R%02d,(R14+$%X)", reg2, convert_zero[reg1]*4);break; |
| 159 | case 50: sprintf(buffer, "STORE R%02d,(R15+$%X)", reg2, convert_zero[reg1]*4);break; |
| 160 | case 51: sprintf(buffer, "MOVE PC,R%02d", reg2); break; |
| 161 | case 52: sprintf(buffer, "JUMP %s(R%02d)", condition[reg2], reg1); break; |
| 162 | case 53: sprintf(buffer, "JR %s$%X", condition[reg2], pc + ((int8_t)(reg1 << 3) >> 2)); break; |
| 163 | case 54: sprintf(buffer, "MMULT R%02d,R%02d", reg1, reg2); break; |
| 164 | case 55: sprintf(buffer, "MTOI R%02d,R%02d", reg1, reg2); break; |
| 165 | case 56: sprintf(buffer, "NORMI R%02d,R%02d", reg1, reg2); break; |
| 166 | case 57: sprintf(buffer, "NOP"); break; |
| 167 | case 58: sprintf(buffer, "LOAD (R14+R%02d),R%02d", reg1, reg2); break; |
| 168 | case 59: sprintf(buffer, "LOAD (R15+R%02d),R%02d", reg1, reg2); break; |
| 169 | case 60: sprintf(buffer, "STORE R%02d,(R14+R%02d)", reg2, reg1); break; |
| 170 | case 61: sprintf(buffer, "STORE R%02d,(R15+R%02d)", reg2, reg1); break; |
| 171 | case 62: if (dsp_type == JAGUAR_GPU) |
| 172 | sprintf(buffer, "SAT24 R%02d", reg2); |
| 173 | else |
| 174 | sprintf(buffer, "illegal [%d,%d]", reg1, reg2); |
| 175 | break; |
| 176 | case 63: if (dsp_type == JAGUAR_GPU) |
| 177 | sprintf(buffer, (reg1 ? "UNPACK R%02d" : "PACK R%02d"), reg2); |
| 178 | else |
| 179 | sprintf(buffer, "ADDQMOD $%X,R%02d", convert_zero[reg1], reg2); |
| 180 | break; |
| 181 | } |
| 182 | |
| 183 | #if 0 |
| 184 | sprintf(bufferOut,"%-24s (%04X)", buffer, op); |
| 185 | #else |
| 186 | if (size == 2) |
| 187 | sprintf(bufferOut, "%04X %-24s", op, buffer); |
| 188 | else |
| 189 | { |
| 190 | uint16_t word1 = ROPCODE(pc), word2 = ROPCODE(pc + 2); |
| 191 | sprintf(bufferOut, "%04X %04X %04X %-24s", op, word1, word2, buffer); |
| 192 | } |
| 193 | #endif |
| 194 | |
| 195 | return size; |
| 196 | } |