37ade45fec51828e9972587b1ba6e7a3c9673f09
[picodrive.git] / cpu / sh2 / mame / sh2pico.c
1 #include "../sh2.h"
2
3 #ifdef DRC_CMP
4 #include "../compiler.c"
5 #define BUSY_LOOP_HACKS 0
6 #else
7 #define BUSY_LOOP_HACKS 1
8 #endif
9
10 // MAME types
11 #ifndef INT8
12 typedef signed char  INT8;
13 typedef signed short INT16;
14 typedef signed int   INT32;
15 typedef unsigned int   UINT32;
16 typedef unsigned short UINT16;
17 typedef unsigned char  UINT8;
18 #endif
19
20 #define RB(sh2, a) p32x_sh2_read8(a,sh2)
21 #define RW(sh2, a) p32x_sh2_read16(a,sh2)
22 #define RL(sh2, a) p32x_sh2_read32(a,sh2)
23 #define WB(sh2, a, d) p32x_sh2_write8(a,d,sh2)
24 #define WW(sh2, a, d) p32x_sh2_write16(a,d,sh2)
25 #define WL(sh2, a, d) p32x_sh2_write32(a,d,sh2)
26
27 // some stuff from sh2comn.h
28 #define T       0x00000001
29 #define S       0x00000002
30 #define I       0x000000f0
31 #define Q       0x00000100
32 #define M       0x00000200
33
34 #define AM      0xc7ffffff
35
36 #define FLAGS   (M|Q|I|S|T)
37
38 #define Rn      ((opcode>>8)&15)
39 #define Rm      ((opcode>>4)&15)
40
41 #define sh2_state SH2
42
43 extern void lprintf(const char *fmt, ...);
44 #define logerror lprintf
45
46 #ifdef SH2_STATS
47 static SH2 sh2_stats;
48 static unsigned int op_refs[0x10000];
49 # define LRN  1
50 # define LRM  2
51 # define LRNM (LRN|LRM)
52 # define rlog(rnm) {   \
53   int op = opcode;     \
54   if ((rnm) & LRN) {   \
55     op &= ~0x0f00;     \
56     sh2_stats.r[Rn]++; \
57   }                    \
58   if ((rnm) & LRM) {   \
59     op &= ~0x00f0;     \
60     sh2_stats.r[Rm]++; \
61   }                    \
62   op_refs[op]++;       \
63 }
64 # define rlog1(x) sh2_stats.r[x]++
65 # define rlog2(x1,x2) sh2_stats.r[x1]++; sh2_stats.r[x2]++
66 #else
67 # define rlog(x)
68 # define rlog1(...)
69 # define rlog2(...)
70 #endif
71
72 #include "sh2.c"
73
74 #ifndef DRC_SH2
75 #ifndef DRC_CMP
76
77 int sh2_execute(SH2 *sh2, int cycles)
78 {
79         UINT32 opcode;
80
81         sh2->icount = sh2->cycles_timeslice = cycles;
82
83         if (sh2->icount <= 0)
84                 goto out;
85
86         do
87         {
88                 if (sh2->delay)
89                 {
90                         sh2->ppc = sh2->delay;
91                         opcode = RW(sh2, sh2->delay);
92                         sh2->pc -= 2;
93                 }
94                 else
95                 {
96                         sh2->ppc = sh2->pc;
97                         opcode = RW(sh2, sh2->pc);
98                 }
99
100                 sh2->delay = 0;
101                 sh2->pc += 2;
102
103                 switch (opcode & ( 15 << 12))
104                 {
105                 case  0<<12: op0000(sh2, opcode); break;
106                 case  1<<12: op0001(sh2, opcode); break;
107                 case  2<<12: op0010(sh2, opcode); break;
108                 case  3<<12: op0011(sh2, opcode); break;
109                 case  4<<12: op0100(sh2, opcode); break;
110                 case  5<<12: op0101(sh2, opcode); break;
111                 case  6<<12: op0110(sh2, opcode); break;
112                 case  7<<12: op0111(sh2, opcode); break;
113                 case  8<<12: op1000(sh2, opcode); break;
114                 case  9<<12: op1001(sh2, opcode); break;
115                 case 10<<12: op1010(sh2, opcode); break;
116                 case 11<<12: op1011(sh2, opcode); break;
117                 case 12<<12: op1100(sh2, opcode); break;
118                 case 13<<12: op1101(sh2, opcode); break;
119                 case 14<<12: op1110(sh2, opcode); break;
120                 default: op1111(sh2, opcode); break;
121                 }
122
123                 sh2->icount--;
124
125                 if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
126                 {
127                         int level = sh2->pending_level;
128                         int vector = sh2->irq_callback(sh2, level);
129                         sh2_do_irq(sh2, level, vector);
130                         sh2->test_irq = 0;
131                 }
132
133         }
134         while (sh2->icount > 0 || sh2->delay);  /* can't interrupt before delay */
135
136 out:
137         return sh2->cycles_timeslice - sh2->icount;
138 }
139
140 #else // if DRC_CMP
141
142 int sh2_execute(SH2 *sh2, int cycles)
143 {
144         static unsigned int base_pc_[2] = { 0, 0 };
145         static unsigned int end_pc_[2] = { 0, 0 };
146         static unsigned char op_flags_[2][BLOCK_INSN_LIMIT];
147         unsigned int *base_pc = &base_pc_[sh2->is_slave];
148         unsigned int *end_pc = &end_pc_[sh2->is_slave];
149         unsigned char *op_flags = op_flags_[sh2->is_slave];
150         unsigned int pc_expect;
151         UINT32 opcode;
152
153         sh2->icount = sh2->cycles_timeslice = cycles;
154
155         if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
156         {
157                 int level = sh2->pending_level;
158                 int vector = sh2->irq_callback(sh2, level);
159                 sh2_do_irq(sh2, level, vector);
160         }
161         pc_expect = sh2->pc;
162
163         if (sh2->icount <= 0)
164                 goto out;
165
166         do
167         {
168                 if (!sh2->delay) {
169                         if (sh2->pc < *base_pc || sh2->pc >= *end_pc) {
170                                 *base_pc = sh2->pc;
171                                 scan_block(*base_pc, sh2->is_slave,
172                                         op_flags, end_pc, NULL);
173                         }
174                         if ((op_flags[(sh2->pc - *base_pc) / 2]
175                                 & OF_BTARGET) || sh2->pc == *base_pc
176                                 || pc_expect != sh2->pc) // branched
177                         {
178                                 pc_expect = sh2->pc;
179                                 if (sh2->icount < 0)
180                                         break;
181                         }
182
183                         do_sh2_trace(sh2, sh2->icount);
184                 }
185                 pc_expect += 2;
186
187                 if (sh2->delay)
188                 {
189                         sh2->ppc = sh2->delay;
190                         opcode = RW(sh2, sh2->delay);
191                         sh2->pc -= 2;
192                 }
193                 else
194                 {
195                         sh2->ppc = sh2->pc;
196                         opcode = RW(sh2, sh2->pc);
197                 }
198
199                 sh2->delay = 0;
200                 sh2->pc += 2;
201
202                 switch (opcode & ( 15 << 12))
203                 {
204                 case  0<<12: op0000(sh2, opcode); break;
205                 case  1<<12: op0001(sh2, opcode); break;
206                 case  2<<12: op0010(sh2, opcode); break;
207                 case  3<<12: op0011(sh2, opcode); break;
208                 case  4<<12: op0100(sh2, opcode); break;
209                 case  5<<12: op0101(sh2, opcode); break;
210                 case  6<<12: op0110(sh2, opcode); break;
211                 case  7<<12: op0111(sh2, opcode); break;
212                 case  8<<12: op1000(sh2, opcode); break;
213                 case  9<<12: op1001(sh2, opcode); break;
214                 case 10<<12: op1010(sh2, opcode); break;
215                 case 11<<12: op1011(sh2, opcode); break;
216                 case 12<<12: op1100(sh2, opcode); break;
217                 case 13<<12: op1101(sh2, opcode); break;
218                 case 14<<12: op1110(sh2, opcode); break;
219                 default: op1111(sh2, opcode); break;
220                 }
221
222                 sh2->icount--;
223
224                 if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
225                 {
226                         int level = sh2->pending_level;
227                         int vector = sh2->irq_callback(sh2, level);
228                         sh2_do_irq(sh2, level, vector);
229                         sh2->test_irq = 0;
230                 }
231
232         }
233         while (1);
234
235 out:
236         return sh2->cycles_timeslice - sh2->icount;
237 }
238
239 #endif // DRC_CMP
240 #endif // DRC_SH2
241
242 #ifdef SH2_STATS
243 #include <stdio.h>
244 #include <string.h>
245 #include "sh2dasm.h"
246
247 void sh2_dump_stats(void)
248 {
249         static const char *rnames[] = {
250                 "R0", "R1", "R2",  "R3",  "R4",  "R5",  "R6",  "R7",
251                 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "SP",
252                 "PC", "", "PR", "SR", "GBR", "VBR", "MACH", "MACL"
253         };
254         long long total;
255         char buff[64];
256         int u, i;
257
258         // dump reg usage
259         total = 0;
260         for (i = 0; i < 24; i++)
261                 total += sh2_stats.r[i];
262
263         for (i = 0; i < 24; i++) {
264                 if (i == 16 || i == 17 || i == 19)
265                         continue;
266                 printf("r %6.3f%% %-4s %9d\n", (double)sh2_stats.r[i] * 100.0 / total,
267                         rnames[i], sh2_stats.r[i]);
268         }
269
270         memset(&sh2_stats, 0, sizeof(sh2_stats));
271
272         // dump ops
273         printf("\n");
274         total = 0;
275         for (i = 0; i < 0x10000; i++)
276                 total += op_refs[i];
277
278         for (u = 0; u < 16; u++) {
279                 int max = 0, op = 0;
280                 for (i = 0; i < 0x10000; i++) {
281                         if (op_refs[i] > max) {
282                                 max = op_refs[i];
283                                 op = i;
284                         }
285                 }
286                 DasmSH2(buff, 0, op);
287                 printf("i %6.3f%% %9d %s\n", (double)op_refs[op] * 100.0 / total,
288                         op_refs[op], buff);
289                 op_refs[op] = 0;
290         }
291         memset(op_refs, 0, sizeof(op_refs));
292 }
293 #endif
294