drc: more timing hacks
[pcsx_rearmed.git] / libpcsxcore / disr3000a.c
CommitLineData
ef79bbde
P
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
26char ostr[256];
27
28// Names of registers
29static 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
35char *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
44typedef 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*********************************************************/
92MakeDisF(disADDI, dName("ADDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
93MakeDisF(disADDIU, dName("ADDIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
94MakeDisF(disANDI, dName("ANDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
95MakeDisF(disORI, dName("ORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
96MakeDisF(disSLTI, dName("SLTI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
97MakeDisF(disSLTIU, dName("SLTIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
98MakeDisF(disXORI, dName("XORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();)
99
100/*********************************************************
101* Register arithmetic *
102* Format: OP rd, rs, rt *
103*********************************************************/
104MakeDisF(disADD, dName("ADD"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
105MakeDisF(disADDU, dName("ADDU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
106MakeDisF(disAND, dName("AND"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
107MakeDisF(disNOR, dName("NOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
108MakeDisF(disOR, dName("OR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
109MakeDisF(disSLT, dName("SLT"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
110MakeDisF(disSLTU, dName("SLTU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
111MakeDisF(disSUB, dName("SUB"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
112MakeDisF(disSUBU, dName("SUBU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
113MakeDisF(disXOR, dName("XOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);)
114
115/*********************************************************
116* Register arithmetic & Register trap logic *
117* Format: OP rs, rt *
118*********************************************************/
119MakeDisF(disDIV, dName("DIV"); dGPR(_Rs_); dGPR(_Rt_);)
120MakeDisF(disDIVU, dName("DIVU"); dGPR(_Rs_); dGPR(_Rt_);)
121MakeDisF(disMULT, dName("MULT"); dGPR(_Rs_); dGPR(_Rt_);)
122MakeDisF(disMULTU, dName("MULTU"); dGPR(_Rs_); dGPR(_Rt_);)
123
124/*********************************************************
125* Register branch logic *
126* Format: OP rs, offset *
127*********************************************************/
128MakeDisF(disBGEZ, dName("BGEZ"); dGPR(_Rs_); dOffset();)
129MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR(_Rs_); dOffset();)
130MakeDisF(disBGTZ, dName("BGTZ"); dGPR(_Rs_); dOffset();)
131MakeDisF(disBLEZ, dName("BLEZ"); dGPR(_Rs_); dOffset();)
132MakeDisF(disBLTZ, dName("BLTZ"); dGPR(_Rs_); dOffset();)
133MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR(_Rs_); dOffset();)
134
135/*********************************************************
136* Shift arithmetic with constant shift *
137* Format: OP rd, rt, sa *
138*********************************************************/
139MakeDisF(disSLL, if (code) { dName("SLL"); dGPR(_Rd_); dGPR(_Rt_); dSa(); } else { dName("NOP"); })
140MakeDisF(disSRA, dName("SRA"); dGPR(_Rd_); dGPR(_Rt_); dSa();)
141MakeDisF(disSRL, dName("SRL"); dGPR(_Rd_); dGPR(_Rt_); dSa();)
142
143/*********************************************************
144* Shift arithmetic with variant register shift *
145* Format: OP rd, rt, rs *
146*********************************************************/
147MakeDisF(disSLLV, dName("SLLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
148MakeDisF(disSRAV, dName("SRAV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);)
149MakeDisF(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*********************************************************/
155MakeDisF(disLUI, dName("LUI"); dGPR(_Rt_); dImm();)
156
157/*********************************************************
158* Move from HI/LO to GPR *
159* Format: OP rd *
160*********************************************************/
161MakeDisF(disMFHI, dName("MFHI"); dGPR(_Rd_); dHI();)
162MakeDisF(disMFLO, dName("MFLO"); dGPR(_Rd_); dLO();)
163
164/*********************************************************
165* Move from GPR to HI/LO *
166* Format: OP rd *
167*********************************************************/
168MakeDisF(disMTHI, dName("MTHI"); dHI(); dGPR(_Rs_);)
169MakeDisF(disMTLO, dName("MTLO"); dLO(); dGPR(_Rs_);)
170
171/*********************************************************
172* Special purpose instructions *
173* Format: OP *
174*********************************************************/
175MakeDisF(disBREAK, dName("BREAK"))
176MakeDisF(disRFE, dName("RFE"))
177MakeDisF(disSYSCALL, dName("SYSCALL"))
178MakeDisF(disHLE, dName("HLE"))
179
180
181MakeDisF(disRTPS, dName("RTPS"))
182MakeDisF(disOP , dName("OP"))
183MakeDisF(disNCLIP, dName("NCLIP"))
184MakeDisF(disDPCS, dName("DPCS"))
185MakeDisF(disINTPL, dName("INTPL"))
186MakeDisF(disMVMVA, dName("MVMVA"))
187MakeDisF(disNCDS , dName("NCDS"))
188MakeDisF(disCDP , dName("CDP"))
189MakeDisF(disNCDT , dName("NCDT"))
190MakeDisF(disNCCS , dName("NCCS"))
191MakeDisF(disCC , dName("CC"))
192MakeDisF(disNCS , dName("NCS"))
193MakeDisF(disNCT , dName("NCT"))
194MakeDisF(disSQR , dName("SQR"))
195MakeDisF(disDCPL , dName("DCPL"))
196MakeDisF(disDPCT , dName("DPCT"))
197MakeDisF(disAVSZ3, dName("AVSZ3"))
198MakeDisF(disAVSZ4, dName("AVSZ4"))
199MakeDisF(disRTPT , dName("RTPT"))
200MakeDisF(disGPF , dName("GPF"))
201MakeDisF(disGPL , dName("GPL"))
202MakeDisF(disNCCT , dName("NCCT"))
203
204MakeDisF(disMFC2, dName("MFC2"); dGPR(_Rt_);)
205MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);)
206MakeDisF(disMTC2, dName("MTC2"); dGPR(_Rt_);)
207MakeDisF(disCTC2, dName("CTC2"); dGPR(_Rt_);)
208
209/*********************************************************
210* Register branch logic *
211* Format: OP rs, rt, offset *
212*********************************************************/
213MakeDisF(disBEQ, dName("BEQ"); dGPR(_Rs_); dGPR(_Rt_); dOffset();)
214MakeDisF(disBNE, dName("BNE"); dGPR(_Rs_); dGPR(_Rt_); dOffset();)
215
216/*********************************************************
217* Jump to target *
218* Format: OP target *
219*********************************************************/
220MakeDisF(disJ, dName("J"); dTarget();)
221MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR(31);)
222
223/*********************************************************
224* Register jump *
225* Format: OP rs, rd *
226*********************************************************/
227MakeDisF(disJR, dName("JR"); dGPR(_Rs_);)
228MakeDisF(disJALR, dName("JALR"); dGPR(_Rs_); dGPR(_Rd_))
229
230/*********************************************************
231* Load and store for GPR *
232* Format: OP rt, offset(base) *
233*********************************************************/
234MakeDisF(disLB, dName("LB"); dGPR(_Rt_); dOfB();)
235MakeDisF(disLBU, dName("LBU"); dGPR(_Rt_); dOfB();)
236MakeDisF(disLH, dName("LH"); dGPR(_Rt_); dOfB();)
237MakeDisF(disLHU, dName("LHU"); dGPR(_Rt_); dOfB();)
238MakeDisF(disLW, dName("LW"); dGPR(_Rt_); dOfB();)
239MakeDisF(disLWL, dName("LWL"); dGPR(_Rt_); dOfB();)
240MakeDisF(disLWR, dName("LWR"); dGPR(_Rt_); dOfB();)
241MakeDisF(disLWC2, dName("LWC2"); dGPR(_Rt_); dOfB();)
242MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();)
243MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();)
244MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();)
245MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();)
246MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();)
247MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();)
248
249/*********************************************************
250* Moves between GPR and COPx *
251* Format: OP rt, fs *
252*********************************************************/
253MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);)
254MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);)
255MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);)
256MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);)
257
258/*********************************************************
259* Unknow instruction (would generate an exception) *
260* Format: ? *
261*********************************************************/
262MakeDisF(disNULL, dName("*** Bad OP ***");)
263
264
265TdisR3000AF 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
275MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc))
276
277TdisR3000AF 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
283MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc))
284
285TdisR3000AF 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
291MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc))
292
293TdisR3000AF 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
299MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc))
300
301TdisR3000AF 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
311MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc))
312
313TdisR3000AF 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
323MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc))