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"
29 static char *disRNameGPR[] = {
30 "r0", "at", "v0", "v1", "a0", "a1","a2", "a3",
31 "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7",
32 "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7",
33 "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra"};
35 char *disRNameCP0[] = {
36 "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*",
37 "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" ,
38 "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" ,
39 "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" };
42 // Type deffinition of our functions
44 typedef char* (*TdisR3000AF)(u32 code, u32 pc);
46 // These macros are used to assemble the disassembler functions
47 #define MakeDisFg(fn, b) char* fn(u32 code, u32 pc) { b; return ostr; }
48 #define MakeDisF(fn, b) \
49 static char* fn(u32 code, u32 pc) { \
50 sprintf (ostr, "%8.8x %8.8x:", pc, code); \
51 b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \
65 #define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register
66 #define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register
67 #define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register
68 #define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register
69 #define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register
70 #define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register
72 #define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4))
73 #define _Branch_ (pc + 4 + ((short)_Im_ * 4))
74 #define _OfB_ _Im_, _nRs_
76 #define dName(i) sprintf(ostr, "%s %-7s,", ostr, i)
77 #define dGPR(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i])
78 #define dCP0(i) sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i])
79 #define dHI() sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.hi, "hi")
80 #define dLO() sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.lo, "lo")
81 #define dImm() sprintf(ostr, "%s %4.4x (%d),", ostr, _Im_, _Im_)
82 #define dTarget() sprintf(ostr, "%s %8.8x,", ostr, _Target_)
83 #define dSa() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_, _Sa_)
84 #define dOfB() sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_])
85 #define dOffset() sprintf(ostr, "%s %8.8x,", ostr, _Branch_)
86 #define dCode() sprintf(ostr, "%s %8.8x,", ostr, (code >> 6) & 0xffffff)
88 /*********************************************************
89 * Arithmetic with immediate operand *
90 * Format: OP rt, rs, immediate *
91 *********************************************************/
92 MakeDisF(disADDI, dName("ADDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
93 MakeDisF(disADDIU, dName("ADDIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
94 MakeDisF(disANDI, dName("ANDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
95 MakeDisF(disORI, dName("ORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
96 MakeDisF(disSLTI, dName("SLTI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
97 MakeDisF(disSLTIU, dName("SLTIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
98 MakeDisF(disXORI, dName("XORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
100 /*********************************************************
101 * Register arithmetic *
102 * Format: OP rd, rs, rt *
103 *********************************************************/
104 MakeDisF(disADD, dName("ADD"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
105 MakeDisF(disADDU, dName("ADDU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
106 MakeDisF(disAND, dName("AND"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
107 MakeDisF(disNOR, dName("NOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
108 MakeDisF(disOR, dName("OR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
109 MakeDisF(disSLT, dName("SLT"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
110 MakeDisF(disSLTU, dName("SLTU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
111 MakeDisF(disSUB, dName("SUB"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
112 MakeDisF(disSUBU, dName("SUBU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
113 MakeDisF(disXOR, dName("XOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
115 /*********************************************************
116 * Register arithmetic & Register trap logic *
117 * Format: OP rs, rt *
118 *********************************************************/
119 MakeDisF(disDIV, dName("DIV"); dGPR(_Rs_); dGPR(_Rt_);)
120 MakeDisF(disDIVU, dName("DIVU"); dGPR(_Rs_); dGPR(_Rt_);)
121 MakeDisF(disMULT, dName("MULT"); dGPR(_Rs_); dGPR(_Rt_);)
122 MakeDisF(disMULTU, dName("MULTU"); dGPR(_Rs_); dGPR(_Rt_);)
124 /*********************************************************
125 * Register branch logic *
126 * Format: OP rs, offset *
127 *********************************************************/
128 MakeDisF(disBGEZ, dName("BGEZ"); dGPR(_Rs_); dOffset();)
129 MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR(_Rs_); dOffset();)
130 MakeDisF(disBGTZ, dName("BGTZ"); dGPR(_Rs_); dOffset();)
131 MakeDisF(disBLEZ, dName("BLEZ"); dGPR(_Rs_); dOffset();)
132 MakeDisF(disBLTZ, dName("BLTZ"); dGPR(_Rs_); dOffset();)
133 MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR(_Rs_); dOffset();)
135 /*********************************************************
136 * Shift arithmetic with constant shift *
137 * Format: OP rd, rt, sa *
138 *********************************************************/
139 MakeDisF(disSLL, if (code) { dName("SLL"); dGPR(_Rd_); dGPR(_Rt_); dSa(); } else { dName("NOP"); })
140 MakeDisF(disSRA, dName("SRA"); dGPR(_Rd_); dGPR(_Rt_); dSa();)
141 MakeDisF(disSRL, dName("SRL"); dGPR(_Rd_); dGPR(_Rt_); dSa();)
143 /*********************************************************
144 * Shift arithmetic with variant register shift *
145 * Format: OP rd, rt, rs *
146 *********************************************************/
147 MakeDisF(disSLLV, dName("SLLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
148 MakeDisF(disSRAV, dName("SRAV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
149 MakeDisF(disSRLV, dName("SRLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
151 /*********************************************************
152 * Load higher 16 bits of the first word in GPR with imm *
153 * Format: OP rt, immediate *
154 *********************************************************/
155 MakeDisF(disLUI, dName("LUI"); dGPR(_Rt_); dImm();)
157 /*********************************************************
158 * Move from HI/LO to GPR *
160 *********************************************************/
161 MakeDisF(disMFHI, dName("MFHI"); dGPR(_Rd_); dHI();)
162 MakeDisF(disMFLO, dName("MFLO"); dGPR(_Rd_); dLO();)
164 /*********************************************************
165 * Move from GPR to HI/LO *
167 *********************************************************/
168 MakeDisF(disMTHI, dName("MTHI"); dHI(); dGPR(_Rs_);)
169 MakeDisF(disMTLO, dName("MTLO"); dLO(); dGPR(_Rs_);)
171 /*********************************************************
172 * Special purpose instructions *
174 *********************************************************/
175 MakeDisF(disBREAK, dName("BREAK"))
176 MakeDisF(disRFE, dName("RFE"))
177 MakeDisF(disSYSCALL, dName("SYSCALL"))
178 MakeDisF(disHLE, dName("HLE"))
181 MakeDisF(disRTPS, dName("RTPS"))
182 MakeDisF(disOP , dName("OP"))
183 MakeDisF(disNCLIP, dName("NCLIP"))
184 MakeDisF(disDPCS, dName("DPCS"))
185 MakeDisF(disINTPL, dName("INTPL"))
186 MakeDisF(disMVMVA, dName("MVMVA"))
187 MakeDisF(disNCDS , dName("NCDS"))
188 MakeDisF(disCDP , dName("CDP"))
189 MakeDisF(disNCDT , dName("NCDT"))
190 MakeDisF(disNCCS , dName("NCCS"))
191 MakeDisF(disCC , dName("CC"))
192 MakeDisF(disNCS , dName("NCS"))
193 MakeDisF(disNCT , dName("NCT"))
194 MakeDisF(disSQR , dName("SQR"))
195 MakeDisF(disDCPL , dName("DCPL"))
196 MakeDisF(disDPCT , dName("DPCT"))
197 MakeDisF(disAVSZ3, dName("AVSZ3"))
198 MakeDisF(disAVSZ4, dName("AVSZ4"))
199 MakeDisF(disRTPT , dName("RTPT"))
200 MakeDisF(disGPF , dName("GPF"))
201 MakeDisF(disGPL , dName("GPL"))
202 MakeDisF(disNCCT , dName("NCCT"))
204 MakeDisF(disMFC2, dName("MFC2"); dGPR(_Rt_);)
205 MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);)
206 MakeDisF(disMTC2, dName("MTC2"); dGPR(_Rt_);)
207 MakeDisF(disCTC2, dName("CTC2"); dGPR(_Rt_);)
209 /*********************************************************
210 * Register branch logic *
211 * Format: OP rs, rt, offset *
212 *********************************************************/
213 MakeDisF(disBEQ, dName("BEQ"); dGPR(_Rs_); dGPR(_Rt_); dOffset();)
214 MakeDisF(disBNE, dName("BNE"); dGPR(_Rs_); dGPR(_Rt_); dOffset();)
216 /*********************************************************
218 * Format: OP target *
219 *********************************************************/
220 MakeDisF(disJ, dName("J"); dTarget();)
221 MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR(31);)
223 /*********************************************************
225 * Format: OP rs, rd *
226 *********************************************************/
227 MakeDisF(disJR, dName("JR"); dGPR(_Rs_);)
228 MakeDisF(disJALR, dName("JALR"); dGPR(_Rs_); dGPR(_Rd_))
230 /*********************************************************
231 * Load and store for GPR *
232 * Format: OP rt, offset(base) *
233 *********************************************************/
234 MakeDisF(disLB, dName("LB"); dGPR(_Rt_); dOfB();)
235 MakeDisF(disLBU, dName("LBU"); dGPR(_Rt_); dOfB();)
236 MakeDisF(disLH, dName("LH"); dGPR(_Rt_); dOfB();)
237 MakeDisF(disLHU, dName("LHU"); dGPR(_Rt_); dOfB();)
238 MakeDisF(disLW, dName("LW"); dGPR(_Rt_); dOfB();)
239 MakeDisF(disLWL, dName("LWL"); dGPR(_Rt_); dOfB();)
240 MakeDisF(disLWR, dName("LWR"); dGPR(_Rt_); dOfB();)
241 MakeDisF(disLWC2, dName("LWC2"); dGPR(_Rt_); dOfB();)
242 MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();)
243 MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();)
244 MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();)
245 MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();)
246 MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();)
247 MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();)
249 /*********************************************************
250 * Moves between GPR and COPx *
251 * Format: OP rt, fs *
252 *********************************************************/
253 MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);)
254 MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);)
255 MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);)
256 MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);)
258 /*********************************************************
259 * Unknow instruction (would generate an exception) *
261 *********************************************************/
262 MakeDisF(disNULL, dName("*** Bad OP ***");)
265 TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL
266 disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV ,
267 disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL ,
268 disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL ,
269 disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL ,
270 disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR ,
271 disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL ,
272 disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL ,
273 disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL};
275 MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc))
277 TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND
278 disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
279 disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
280 disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
281 disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL};
283 MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc))
285 TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0
286 disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL,
287 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
288 disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
289 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL};
291 MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc))
293 TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs)
294 disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL,
295 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
296 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,
297 disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL};
299 MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc))
301 TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct)
302 disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL,
303 disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL,
304 disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL,
305 disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL,
306 disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL,
307 disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL,
308 disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL,
309 disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT };
311 MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc))
313 TdisR3000AF disR3000A[] = {
314 disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ ,
315 disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI ,
316 disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL ,
317 disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL ,
318 disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL ,
319 disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL ,
320 disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL ,
321 disNULL , disNULL , disSWC2 , disHLE , disNULL, disNULL, disNULL , disNULL };
323 MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc))