1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
18 ***************************************************************************/
21 * R3000A disassembler.
24 #include "psxcommon.h"
26 // XXX: don't care but maybe fix it someday
27 #if defined(__GNUC__) && __GNUC__ >= 7
28 #pragma GCC diagnostic ignored "-Wrestrict"
34 static char *disRNameGPR[] = {
35 "r0", "at", "v0", "v1", "a0", "a1","a2", "a3",
36 "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7",
37 "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7",
38 "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra"};
40 char *disRNameCP0[] = {
41 "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*",
42 "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" ,
43 "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" ,
44 "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" };
47 // Type deffinition of our functions
49 typedef char* (*TdisR3000AF)(u32 code, u32 pc);
51 // These macros are used to assemble the disassembler functions
52 #define MakeDisFg(fn, b) char* fn(u32 code, u32 pc) { b; return ostr; }
53 #define MakeDisF(fn, b) \
54 static char* fn(u32 code, u32 pc) { \
55 sprintf (ostr, "%8.8x %8.8x:", pc, code); \
56 b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \
70 #define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register
71 #define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register
72 #define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register
73 #define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register
74 #define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register
75 #define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register
77 #define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4))
78 #define _Branch_ (pc + 4 + ((short)_Im_ * 4))
79 #define _OfB_ _Im_, _nRs_
81 #define dName(i) snprintf(ostr, sizeof(ostr), "%s %-7s,", ostr, i)
82 #define dGPR(i) snprintf(ostr, sizeof(ostr), "%s %8.8x (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i])
83 #define dCP0(i) snprintf(ostr, sizeof(ostr), "%s %8.8x (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i])
84 #define dHI() snprintf(ostr, sizeof(ostr), "%s %8.8x (%s),", ostr, psxRegs.GPR.n.hi, "hi")
85 #define dLO() snprintf(ostr, sizeof(ostr), "%s %8.8x (%s),", ostr, psxRegs.GPR.n.lo, "lo")
86 #define dImm() snprintf(ostr, sizeof(ostr), "%s %4.4x (%d),", ostr, _Im_, _Im_)
87 #define dTarget() snprintf(ostr, sizeof(ostr), "%s %8.8x,", ostr, _Target_)
88 #define dSa() snprintf(ostr, sizeof(ostr), "%s %2.2x (%d),", ostr, _Sa_, _Sa_)
89 #define dOfB() snprintf(ostr, sizeof(ostr), "%s %4.4x (%8.8x (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_])
90 #define dOffset() snprintf(ostr, sizeof(ostr), "%s %8.8x,", ostr, _Branch_)
91 #define dCode() snprintf(ostr, sizeof(ostr), "%s %8.8x,", ostr, (code >> 6) & 0xffffff)
93 /*********************************************************
94 * Arithmetic with immediate operand *
95 * Format: OP rt, rs, immediate *
96 *********************************************************/
97 MakeDisF(disADDI, dName("ADDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
98 MakeDisF(disADDIU, dName("ADDIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
99 MakeDisF(disANDI, dName("ANDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
100 MakeDisF(disORI, dName("ORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
101 MakeDisF(disSLTI, dName("SLTI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
102 MakeDisF(disSLTIU, dName("SLTIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
103 MakeDisF(disXORI, dName("XORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
105 /*********************************************************
106 * Register arithmetic *
107 * Format: OP rd, rs, rt *
108 *********************************************************/
109 MakeDisF(disADD, dName("ADD"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
110 MakeDisF(disADDU, dName("ADDU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
111 MakeDisF(disAND, dName("AND"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
112 MakeDisF(disNOR, dName("NOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
113 MakeDisF(disOR, dName("OR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
114 MakeDisF(disSLT, dName("SLT"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
115 MakeDisF(disSLTU, dName("SLTU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
116 MakeDisF(disSUB, dName("SUB"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
117 MakeDisF(disSUBU, dName("SUBU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
118 MakeDisF(disXOR, dName("XOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
120 /*********************************************************
121 * Register arithmetic & Register trap logic *
122 * Format: OP rs, rt *
123 *********************************************************/
124 MakeDisF(disDIV, dName("DIV"); dGPR(_Rs_); dGPR(_Rt_);)
125 MakeDisF(disDIVU, dName("DIVU"); dGPR(_Rs_); dGPR(_Rt_);)
126 MakeDisF(disMULT, dName("MULT"); dGPR(_Rs_); dGPR(_Rt_);)
127 MakeDisF(disMULTU, dName("MULTU"); dGPR(_Rs_); dGPR(_Rt_);)
129 /*********************************************************
130 * Register branch logic *
131 * Format: OP rs, offset *
132 *********************************************************/
133 MakeDisF(disBGEZ, dName("BGEZ"); dGPR(_Rs_); dOffset();)
134 MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR(_Rs_); dOffset();)
135 MakeDisF(disBGTZ, dName("BGTZ"); dGPR(_Rs_); dOffset();)
136 MakeDisF(disBLEZ, dName("BLEZ"); dGPR(_Rs_); dOffset();)
137 MakeDisF(disBLTZ, dName("BLTZ"); dGPR(_Rs_); dOffset();)
138 MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR(_Rs_); dOffset();)
140 /*********************************************************
141 * Shift arithmetic with constant shift *
142 * Format: OP rd, rt, sa *
143 *********************************************************/
144 MakeDisF(disSLL, if (code) { dName("SLL"); dGPR(_Rd_); dGPR(_Rt_); dSa(); } else { dName("NOP"); })
145 MakeDisF(disSRA, dName("SRA"); dGPR(_Rd_); dGPR(_Rt_); dSa();)
146 MakeDisF(disSRL, dName("SRL"); dGPR(_Rd_); dGPR(_Rt_); dSa();)
148 /*********************************************************
149 * Shift arithmetic with variant register shift *
150 * Format: OP rd, rt, rs *
151 *********************************************************/
152 MakeDisF(disSLLV, dName("SLLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
153 MakeDisF(disSRAV, dName("SRAV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
154 MakeDisF(disSRLV, dName("SRLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
156 /*********************************************************
157 * Load higher 16 bits of the first word in GPR with imm *
158 * Format: OP rt, immediate *
159 *********************************************************/
160 MakeDisF(disLUI, dName("LUI"); dGPR(_Rt_); dImm();)
162 /*********************************************************
163 * Move from HI/LO to GPR *
165 *********************************************************/
166 MakeDisF(disMFHI, dName("MFHI"); dGPR(_Rd_); dHI();)
167 MakeDisF(disMFLO, dName("MFLO"); dGPR(_Rd_); dLO();)
169 /*********************************************************
170 * Move from GPR to HI/LO *
172 *********************************************************/
173 MakeDisF(disMTHI, dName("MTHI"); dHI(); dGPR(_Rs_);)
174 MakeDisF(disMTLO, dName("MTLO"); dLO(); dGPR(_Rs_);)
176 /*********************************************************
177 * Special purpose instructions *
179 *********************************************************/
180 MakeDisF(disBREAK, dName("BREAK"))
181 MakeDisF(disRFE, dName("RFE"))
182 MakeDisF(disSYSCALL, dName("SYSCALL"))
183 MakeDisF(disHLE, dName("HLE"))
186 MakeDisF(disRTPS, dName("RTPS"))
187 MakeDisF(disOP , dName("OP"))
188 MakeDisF(disNCLIP, dName("NCLIP"))
189 MakeDisF(disDPCS, dName("DPCS"))
190 MakeDisF(disINTPL, dName("INTPL"))
191 MakeDisF(disMVMVA, dName("MVMVA"))
192 MakeDisF(disNCDS , dName("NCDS"))
193 MakeDisF(disCDP , dName("CDP"))
194 MakeDisF(disNCDT , dName("NCDT"))
195 MakeDisF(disNCCS , dName("NCCS"))
196 MakeDisF(disCC , dName("CC"))
197 MakeDisF(disNCS , dName("NCS"))
198 MakeDisF(disNCT , dName("NCT"))
199 MakeDisF(disSQR , dName("SQR"))
200 MakeDisF(disDCPL , dName("DCPL"))
201 MakeDisF(disDPCT , dName("DPCT"))
202 MakeDisF(disAVSZ3, dName("AVSZ3"))
203 MakeDisF(disAVSZ4, dName("AVSZ4"))
204 MakeDisF(disRTPT , dName("RTPT"))
205 MakeDisF(disGPF , dName("GPF"))
206 MakeDisF(disGPL , dName("GPL"))
207 MakeDisF(disNCCT , dName("NCCT"))
209 MakeDisF(disMFC2, dName("MFC2"); dGPR(_Rt_);)
210 MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);)
211 MakeDisF(disMTC2, dName("MTC2"); dGPR(_Rt_);)
212 MakeDisF(disCTC2, dName("CTC2"); dGPR(_Rt_);)
214 /*********************************************************
215 * Register branch logic *
216 * Format: OP rs, rt, offset *
217 *********************************************************/
218 MakeDisF(disBEQ, dName("BEQ"); dGPR(_Rs_); dGPR(_Rt_); dOffset();)
219 MakeDisF(disBNE, dName("BNE"); dGPR(_Rs_); dGPR(_Rt_); dOffset();)
221 /*********************************************************
223 * Format: OP target *
224 *********************************************************/
225 MakeDisF(disJ, dName("J"); dTarget();)
226 MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR(31);)
228 /*********************************************************
230 * Format: OP rs, rd *
231 *********************************************************/
232 MakeDisF(disJR, dName("JR"); dGPR(_Rs_);)
233 MakeDisF(disJALR, dName("JALR"); dGPR(_Rs_); dGPR(_Rd_))
235 /*********************************************************
236 * Load and store for GPR *
237 * Format: OP rt, offset(base) *
238 *********************************************************/
239 MakeDisF(disLB, dName("LB"); dGPR(_Rt_); dOfB();)
240 MakeDisF(disLBU, dName("LBU"); dGPR(_Rt_); dOfB();)
241 MakeDisF(disLH, dName("LH"); dGPR(_Rt_); dOfB();)
242 MakeDisF(disLHU, dName("LHU"); dGPR(_Rt_); dOfB();)
243 MakeDisF(disLW, dName("LW"); dGPR(_Rt_); dOfB();)
244 MakeDisF(disLWL, dName("LWL"); dGPR(_Rt_); dOfB();)
245 MakeDisF(disLWR, dName("LWR"); dGPR(_Rt_); dOfB();)
246 MakeDisF(disLWC2, dName("LWC2"); dGPR(_Rt_); dOfB();)
247 MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();)
248 MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();)
249 MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();)
250 MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();)
251 MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();)
252 MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();)
254 /*********************************************************
255 * Moves between GPR and COPx *
256 * Format: OP rt, fs *
257 *********************************************************/
258 MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);)
259 MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);)
260 MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);)
261 MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);)
263 /*********************************************************
264 * Unknow instruction (would generate an exception) *
266 *********************************************************/
267 MakeDisF(disNULL, dName("*** Bad OP ***");)
270 TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL
271 disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV ,
272 disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL ,
273 disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL ,
274 disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL ,
275 disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR ,
276 disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL ,
277 disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL ,
278 disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL};
280 MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc))
282 TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND
283 disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
284 disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
285 disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
286 disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL};
288 MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc))
290 TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0
291 disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL,
292 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
293 disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
294 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL};
296 MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc))
298 TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs)
299 disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL,
300 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
301 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
302 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL};
304 MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc))
306 TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct)
307 disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL,
308 disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL,
309 disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL,
310 disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL,
311 disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL,
312 disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL,
313 disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL,
314 disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT };
316 MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc))
318 TdisR3000AF disR3000A[] = {
319 disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ ,
320 disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI ,
321 disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL ,
322 disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL ,
323 disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL ,
324 disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL ,
325 disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL ,
326 disNULL , disNULL , disSWC2 , disHLE , disNULL, disNULL, disNULL , disNULL };
328 MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc))