dfxvideo: make fskip update on vsync too
[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 char ostr[256];
27
28 // Names of registers
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"};
34
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*"     };
40
41
42 // Type deffinition of our functions
43
44 typedef char* (*TdisR3000AF)(u32 code, u32 pc);
45
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; \
52         }
53
54
55 #include "r3000a.h"
56
57 #undef _Funct_
58 #undef _Rd_
59 #undef _Rt_
60 #undef _Rs_
61 #undef _Sa_
62 #undef _Im_
63 #undef _Target_
64
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
71
72 #define _Target_  ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4))
73 #define _Branch_  (pc + 4 + ((short)_Im_ * 4))
74 #define _OfB_     _Im_, _nRs_
75
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)
87
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();)
99
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_);)
114
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_);)
123
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();)
134
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();)
142
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_);)
150
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();)
156
157 /*********************************************************
158 * Move from HI/LO to GPR                                 *
159 * Format:  OP rd                                         *
160 *********************************************************/
161 MakeDisF(disMFHI,               dName("MFHI"); dGPR(_Rd_); dHI();)
162 MakeDisF(disMFLO,               dName("MFLO"); dGPR(_Rd_); dLO();)
163
164 /*********************************************************
165 * Move from GPR to HI/LO                                 *
166 * Format:  OP rd                                         *
167 *********************************************************/
168 MakeDisF(disMTHI,               dName("MTHI"); dHI(); dGPR(_Rs_);)
169 MakeDisF(disMTLO,               dName("MTLO"); dLO(); dGPR(_Rs_);)
170
171 /*********************************************************
172 * Special purpose instructions                           *
173 * Format:  OP                                            *
174 *********************************************************/
175 MakeDisF(disBREAK,              dName("BREAK"))
176 MakeDisF(disRFE,                dName("RFE"))
177 MakeDisF(disSYSCALL,    dName("SYSCALL"))
178 MakeDisF(disHLE,                dName("HLE"))
179
180
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"))
203
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_);)
208
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();)
215
216 /*********************************************************
217 * Jump to target                                         *
218 * Format:  OP target                                     *
219 *********************************************************/
220 MakeDisF(disJ,                  dName("J");   dTarget();)
221 MakeDisF(disJAL,                dName("JAL"); dTarget(); dGPR(31);)
222
223 /*********************************************************
224 * Register jump                                          *
225 * Format:  OP rs, rd                                     *
226 *********************************************************/
227 MakeDisF(disJR,                 dName("JR");   dGPR(_Rs_);)
228 MakeDisF(disJALR,               dName("JALR"); dGPR(_Rs_); dGPR(_Rd_))
229
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();)
248
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_);)
257
258 /*********************************************************
259 * Unknow instruction (would generate an exception)       *
260 * Format:  ?                                             *
261 *********************************************************/
262 MakeDisF(disNULL,               dName("*** Bad OP ***");)
263
264
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};
274
275 MakeDisF(disSPECIAL,    disR3000A_SPECIAL[_Funct_](code, pc))
276
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};
282
283 MakeDisF(disBCOND,      disR3000A_BCOND[_Rt_](code, pc))
284
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};
290
291 MakeDisF(disCOP0,               disR3000A_COP0[_Rs_](code, pc))
292
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};
298
299 MakeDisF(disBASIC,              disR3000A_BASIC[_Rs_](code, pc))
300
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   };
310
311 MakeDisF(disCOP2,               disR3000A_COP2[_Funct_](code, pc))
312
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 };
322
323 MakeDisFg(disR3000AF,   disR3000A[code >> 26](code, pc))