deal with some more annoying warnings
[pcsx_rearmed.git] / libpcsxcore / disr3000a.c
1 /***************************************************************************
2  *   Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team              *
3  *                                                                         *
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.                                   *
8  *                                                                         *
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.                          *
13  *                                                                         *
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  ***************************************************************************/
19
20 /* 
21 * R3000A disassembler.
22 */
23
24 #include "psxcommon.h"
25
26 // XXX: don't care but maybe fix it someday
27 #if defined(__GNUC__) && __GNUC__ >= 7
28 #pragma GCC diagnostic ignored "-Wrestrict"
29 #endif
30
31 char ostr[256];
32
33 // Names of registers
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"};
39
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*"     };
45
46
47 // Type deffinition of our functions
48
49 typedef char* (*TdisR3000AF)(u32 code, u32 pc);
50
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; \
57         }
58
59
60 #include "r3000a.h"
61
62 #undef _Funct_
63 #undef _Rd_
64 #undef _Rt_
65 #undef _Rs_
66 #undef _Sa_
67 #undef _Im_
68 #undef _Target_
69
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
76
77 #define _Target_  ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4))
78 #define _Branch_  (pc + 4 + ((short)_Im_ * 4))
79 #define _OfB_     _Im_, _nRs_
80
81 #define dName(i)        sprintf(ostr, "%s %-7s,", ostr, i)
82 #define dGPR(i)         sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i])
83 #define dCP0(i)         sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i])
84 #define dHI()           sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.hi, "hi")
85 #define dLO()           sprintf(ostr, "%s %8.8x (%s),", ostr, psxRegs.GPR.n.lo, "lo")
86 #define dImm()          sprintf(ostr, "%s %4.4x (%d),", ostr, _Im_, _Im_)
87 #define dTarget()       sprintf(ostr, "%s %8.8x,", ostr, _Target_)
88 #define dSa()           sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_, _Sa_)
89 #define dOfB()          sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_])
90 #define dOffset()       sprintf(ostr, "%s %8.8x,", ostr, _Branch_)
91 #define dCode()         sprintf(ostr, "%s %8.8x,", ostr, (code >> 6) & 0xffffff)
92
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();)
104
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_);)
119
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_);)
128
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();)
139
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();)
147
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_);)
155
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();)
161
162 /*********************************************************
163 * Move from HI/LO to GPR                                 *
164 * Format:  OP rd                                         *
165 *********************************************************/
166 MakeDisF(disMFHI,               dName("MFHI"); dGPR(_Rd_); dHI();)
167 MakeDisF(disMFLO,               dName("MFLO"); dGPR(_Rd_); dLO();)
168
169 /*********************************************************
170 * Move from GPR to HI/LO                                 *
171 * Format:  OP rd                                         *
172 *********************************************************/
173 MakeDisF(disMTHI,               dName("MTHI"); dHI(); dGPR(_Rs_);)
174 MakeDisF(disMTLO,               dName("MTLO"); dLO(); dGPR(_Rs_);)
175
176 /*********************************************************
177 * Special purpose instructions                           *
178 * Format:  OP                                            *
179 *********************************************************/
180 MakeDisF(disBREAK,              dName("BREAK"))
181 MakeDisF(disRFE,                dName("RFE"))
182 MakeDisF(disSYSCALL,    dName("SYSCALL"))
183 MakeDisF(disHLE,                dName("HLE"))
184
185
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"))
208
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_);)
213
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();)
220
221 /*********************************************************
222 * Jump to target                                         *
223 * Format:  OP target                                     *
224 *********************************************************/
225 MakeDisF(disJ,                  dName("J");   dTarget();)
226 MakeDisF(disJAL,                dName("JAL"); dTarget(); dGPR(31);)
227
228 /*********************************************************
229 * Register jump                                          *
230 * Format:  OP rs, rd                                     *
231 *********************************************************/
232 MakeDisF(disJR,                 dName("JR");   dGPR(_Rs_);)
233 MakeDisF(disJALR,               dName("JALR"); dGPR(_Rs_); dGPR(_Rd_))
234
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();)
253
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_);)
262
263 /*********************************************************
264 * Unknow instruction (would generate an exception)       *
265 * Format:  ?                                             *
266 *********************************************************/
267 MakeDisF(disNULL,               dName("*** Bad OP ***");)
268
269
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};
279
280 MakeDisF(disSPECIAL,    disR3000A_SPECIAL[_Funct_](code, pc))
281
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};
287
288 MakeDisF(disBCOND,      disR3000A_BCOND[_Rt_](code, pc))
289
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};
295
296 MakeDisF(disCOP0,               disR3000A_COP0[_Rs_](code, pc))
297
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};
303
304 MakeDisF(disBASIC,              disR3000A_BASIC[_Rs_](code, pc))
305
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   };
315
316 MakeDisF(disCOP2,               disR3000A_COP2[_Funct_](code, pc))
317
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 };
327
328 MakeDisFg(disR3000AF,   disR3000A[code >> 26](code, pc))