more MAME fixes, some optimization
[picodrive.git] / cpu / Cyclone / Ea.cpp
CommitLineData
cc68a136 1\r
2#include "app.h"\r
3\r
4// some ops use non-standard cycle counts for EAs, so are listed here.\r
5// all constants borrowed from the MUSASHI core by Karl Stenerud.\r
6\r
7/* Extra cycles for JMP instruction (000, 010) */\r
8int g_jmp_cycle_table[8] =\r
9{\r
10 4, /* EA_MODE_AI */\r
11 6, /* EA_MODE_DI */\r
12 10, /* EA_MODE_IX */\r
13 6, /* EA_MODE_AW */\r
14 8, /* EA_MODE_AL */\r
15 6, /* EA_MODE_PCDI */\r
16 10, /* EA_MODE_PCIX */\r
17 0, /* EA_MODE_I */\r
18};\r
19\r
20/* Extra cycles for JSR instruction (000, 010) */\r
21int g_jsr_cycle_table[8] =\r
22{\r
23 4, /* EA_MODE_AI */\r
24 6, /* EA_MODE_DI */\r
25 10, /* EA_MODE_IX */\r
26 6, /* EA_MODE_AW */\r
27 8, /* EA_MODE_AL */\r
28 6, /* EA_MODE_PCDI */\r
29 10, /* EA_MODE_PCIX */\r
30 0, /* EA_MODE_I */\r
31};\r
32\r
33/* Extra cycles for LEA instruction (000, 010) */\r
34int g_lea_cycle_table[8] =\r
35{\r
36 4, /* EA_MODE_AI */\r
37 8, /* EA_MODE_DI */\r
38 12, /* EA_MODE_IX */\r
39 8, /* EA_MODE_AW */\r
40 12, /* EA_MODE_AL */\r
41 8, /* EA_MODE_PCDI */\r
42 12, /* EA_MODE_PCIX */\r
43 0, /* EA_MODE_I */\r
44};\r
45\r
46/* Extra cycles for PEA instruction (000, 010) */\r
47int g_pea_cycle_table[8] =\r
48{\r
49 6, /* EA_MODE_AI */\r
50 10, /* EA_MODE_DI */\r
51 14, /* EA_MODE_IX */\r
52 10, /* EA_MODE_AW */\r
53 14, /* EA_MODE_AL */\r
54 10, /* EA_MODE_PCDI */\r
55 14, /* EA_MODE_PCIX */\r
56 0, /* EA_MODE_I */\r
57};\r
58\r
59/* Extra cycles for MOVEM instruction (000, 010) */\r
60int g_movem_cycle_table[8] =\r
61{\r
62 0, /* EA_MODE_AI */\r
63 4, /* EA_MODE_DI */\r
64 6, /* EA_MODE_IX */\r
65 4, /* EA_MODE_AW */\r
66 8, /* EA_MODE_AL */\r
67 0, /* EA_MODE_PCDI */\r
68 0, /* EA_MODE_PCIX */\r
69 0, /* EA_MODE_I */\r
70};\r
71\r
72// add nonstandard EA\r
73int Ea_add_ns(int *tab, int ea)\r
74{\r
a6785576 75 if(ea<0x10) return 0;\r
76 if((ea&0x38)==0x10) return tab[0]; // (An) (ai)\r
77 if(ea<0x28) return 0;\r
78 if(ea<0x30) return tab[1]; // ($nn,An) (di)\r
79 if(ea<0x38) return tab[2]; // ($nn,An,Rn) (ix)\r
80 if(ea==0x38) return tab[3]; // (aw)\r
81 if(ea==0x39) return tab[4]; // (al)\r
82 if(ea==0x3a) return tab[5]; // ($nn,PC) (pcdi)\r
83 if(ea==0x3b) return tab[6]; // ($nn,pc,Rn) (pcix)\r
84 if(ea==0x3c) return tab[7]; // #$nnnn (i)\r
85 return 0;\r
cc68a136 86}\r
87\r
88\r
89// ---------------------------------------------------------------------------\r
90// Gets the offset of a register for an ea, and puts it in 'r'\r
91// Shifted left by 'shift'\r
92// Doesn't trash anything\r
93static int EaCalcReg(int r,int ea,int mask,int forceor,int shift,int noshift=0)\r
94{\r
95 int i=0,low=0,needor=0;\r
96 int lsl=0;\r
97\r
98 for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
99 mask&=0xf<<low; // This is the max we can do\r
100\r
101 if (ea>=8) needor=1; // Need to OR to access A0-7\r
102\r
103 if ((mask>>low)&8) if (ea&8) needor=0; // Ah - no we don't actually need to or, since the bit is high in r8\r
104\r
105 if (forceor) needor=1; // Special case for 0x30-0x38 EAs ;)\r
106\r
107 ot(" and r%d,r8,#0x%.4x\n",r,mask);\r
108 if (needor) ot(" orr r%d,r%d,#0x%x ;@ A0-7\n",r,r,8<<low);\r
109\r
110 // Find out amount to shift left:\r
111 lsl=shift-low;\r
112\r
113 if (lsl&&!noshift)\r
114 {\r
115 ot(" mov r%d,r%d,",r,r);\r
116 if (lsl>0) ot("lsl #%d\n", lsl);\r
117 else ot("lsr #%d\n",-lsl);\r
118 }\r
119\r
120 return 0;\r
121}\r
122\r
123// EaCalc - ARM Register 'a' = Effective Address\r
124// Trashes r0,r2 and r3\r
125// size values 0, 1, 2 ~ byte, word, long\r
126int EaCalc(int a,int mask,int ea,int size,int top)\r
127{\r
128 char text[32]="";\r
129 int func=0;\r
130\r
131 DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
132 func=0x68+(size<<2); // Get correct read handler\r
133\r
134 if (ea<0x10)\r
135 {\r
136 int noshift=0;\r
137 if (size>=2||(size==0&&top)) noshift=1; // Saves one opcode\r
138\r
139 ot(";@ EaCalc : Get register index into r%d:\n",a);\r
140\r
141 EaCalcReg(a,ea,mask,0,2,noshift);\r
142 return 0;\r
143 }\r
144 \r
145 ot(";@ EaCalc : Get '%s' into r%d:\n",text,a);\r
146 // (An), (An)+, -(An)\r
147 if (ea<0x28)\r
148 {\r
149 int step=1<<size, strr=a;\r
a6785576 150 int low=0,lsl,i;\r
cc68a136 151\r
152 if ((ea&7)==7 && step<2) step=2; // move.b (a7)+ or -(a7) steps by 2 not 1\r
153\r
154 EaCalcReg(2,ea,mask,0,0,1);\r
a6785576 155 if(mask)\r
cc68a136 156 for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
a6785576 157 lsl=2-low; // Having a lsl #x here saves one opcode\r
cc68a136 158 if (lsl>=0) ot(" ldr r%d,[r7,r2,lsl #%i]\n",a,lsl);\r
159 else if (lsl<0) ot(" ldr r%d,[r7,r2,lsr #%i]\n",a,-lsl);\r
160\r
161 if ((ea&0x38)==0x18) // (An)+\r
a6785576 162 {\r
cc68a136 163 ot(" add r3,r%d,#%d ;@ Post-increment An\n",a,step);\r
a6785576 164 strr=3;\r
165 }\r
cc68a136 166\r
167 if ((ea&0x38)==0x20) // -(An)\r
168 ot(" sub r%d,r%d,#%d ;@ Pre-decrement An\n",a,a,step);\r
169\r
170 if ((ea&0x38)==0x18||(ea&0x38)==0x20)\r
a6785576 171 {\r
cc68a136 172 if (lsl>=0) ot(" str r%d,[r7,r2,lsl #%i]\n",strr,lsl);\r
173 else if (lsl<0) ot(" str r%d,[r7,r2,lsr #%i]\n",strr,-lsl);\r
174 }\r
175\r
176 if ((ea&0x38)==0x20) Cycles+=size<2 ? 6:10; // -(An) Extra cycles\r
177 else Cycles+=size<2 ? 4:8; // (An),(An)+ Extra cycles\r
178 return 0;\r
179 }\r
180\r
181 if (ea<0x30) // ($nn,An) (di)\r
182 {\r
183 EaCalcReg(2,8,mask,0,0);\r
cfb3dfa0 184 ot(" ldrsh r0,[r4],#2 ;@ Fetch offset\n"); pc_dirty=1;\r
cc68a136 185 ot(" ldr r2,[r7,r2,lsl #2]\n");\r
186 ot(" add r%d,r0,r2 ;@ Add on offset\n",a);\r
187 Cycles+=size<2 ? 8:12; // Extra cycles\r
188 return 0;\r
189 }\r
190\r
191 if (ea<0x38) // ($nn,An,Rn) (ix)\r
192 {\r
193 ot(";@ Get extension word into r3:\n");\r
cfb3dfa0 194 ot(" ldrh r3,[r4],#2 ;@ ($Disp,PC,Rn)\n"); pc_dirty=1;\r
cc68a136 195 ot(" mov r2,r3,lsr #10\n");\r
196 ot(" tst r3,#0x0800 ;@ Is Rn Word or Long\n");\r
197 ot(" and r2,r2,#0x3c ;@ r2=Index of Rn\n");\r
198 ot(" ldreqsh r2,[r7,r2] ;@ r2=Rn.w\n");\r
199 ot(" ldrne r2,[r7,r2] ;@ r2=Rn.l\n");\r
200 ot(" mov r0,r3,asl #24 ;@ r0=Get 8-bit signed Disp\n");\r
201 ot(" add r3,r2,r0,asr #24 ;@ r3=Disp+Rn\n");\r
202\r
203 EaCalcReg(2,8,mask,1,0);\r
204 ot(" ldr r2,[r7,r2,lsl #2]\n");\r
205 ot(" add r%d,r2,r3 ;@ r%d=Disp+An+Rn\n",a,a);\r
206 Cycles+=size<2 ? 10:14; // Extra cycles\r
207 return 0;\r
208 }\r
209\r
210 if (ea==0x38) // (aw)\r
211 {\r
cfb3dfa0 212 ot(" ldrsh r%d,[r4],#2 ;@ Fetch Absolute Short address\n",a); pc_dirty=1;\r
cc68a136 213 Cycles+=size<2 ? 8:12; // Extra cycles\r
214 return 0;\r
215 }\r
216\r
217 if (ea==0x39) // (al)\r
218 {\r
219 ot(" ldrh r2,[r4],#2 ;@ Fetch Absolute Long address\n");\r
cfb3dfa0 220 ot(" ldrh r0,[r4],#2\n"); pc_dirty=1;\r
cc68a136 221 ot(" orr r%d,r0,r2,lsl #16\n",a);\r
222 Cycles+=size<2 ? 12:16; // Extra cycles\r
223 return 0;\r
224 }\r
225\r
226 if (ea==0x3a) // ($nn,PC) (pcdi)\r
227 {\r
228 ot(" ldr r0,[r7,#0x60] ;@ Get Memory base\n");\r
229 ot(" sub r0,r4,r0 ;@ Real PC\n");\r
cfb3dfa0 230 ot(" ldrsh r2,[r4],#2 ;@ Fetch extension\n"); pc_dirty=1;\r
cc68a136 231 ot(" mov r0,r0,lsl #8\n");\r
232 ot(" add r%d,r2,r0,asr #8 ;@ ($nn,PC)\n",a);\r
233 Cycles+=size<2 ? 8:12; // Extra cycles\r
234 return 0;\r
235 }\r
236\r
237 if (ea==0x3b) // ($nn,pc,Rn) (pcix)\r
238 {\r
239 ot(" ldr r0,[r7,#0x60] ;@ Get Memory base\n");\r
240 ot(" ldrh r3,[r4] ;@ Get extension word\n");\r
241 ot(" sub r0,r4,r0 ;@ r0=PC\n");\r
cfb3dfa0 242 ot(" add r4,r4,#2\n"); pc_dirty=1;\r
cc68a136 243 ot(" mov r0,r0,asl #8 ;@ use only 24bits of PC\n");\r
244 ot(" mov r2,r3,lsr #10\n");\r
245 ot(" tst r3,#0x0800 ;@ Is Rn Word or Long\n");\r
246 ot(" and r2,r2,#0x3c ;@ r2=Index of Rn\n");\r
247 ot(" ldreqsh r2,[r7,r2] ;@ r2=Rn.w\n");\r
248 ot(" ldrne r2,[r7,r2] ;@ r2=Rn.l\n");\r
249 ot(" mov r3,r3,asl #24 ;@ r3=Get 8-bit signed Disp\n");\r
250 ot(" add r2,r2,r3,asr #24 ;@ r2=Disp+Rn\n");\r
251 ot(" add r%d,r2,r0,asr #8 ;@ r%d=Disp+PC+Rn\n",a,a);\r
252 Cycles+=size<2 ? 10:14; // Extra cycles\r
253 return 0;\r
254 }\r
255\r
256 if (ea==0x3c) // #$nnnn (i)\r
257 {\r
258 if (size<2)\r
259 {\r
cfb3dfa0 260 ot(" ldr%s r%d,[r4],#2 ;@ Fetch immediate value\n",Sarm[size&3],a); pc_dirty=1;\r
cc68a136 261 Cycles+=4; // Extra cycles\r
262 return 0;\r
263 }\r
264\r
265 ot(" ldrh r2,[r4],#2 ;@ Fetch immediate value\n");\r
cfb3dfa0 266 ot(" ldrh r0,[r4],#2\n"); pc_dirty=1;\r
cc68a136 267 ot(" orr r%d,r0,r2,lsl #16\n",a);\r
268 Cycles+=8; // Extra cycles\r
269 return 0;\r
270 }\r
271\r
272 return 1;\r
273}\r
274\r
275// ---------------------------------------------------------------------------\r
276// Read effective address in (ARM Register 'a') to ARM register 'v'\r
277// 'a' and 'v' can be anything but 0 is generally best (for both)\r
278// If (ea<0x10) nothing is trashed, else r0-r3 is trashed\r
279// If 'top' is given, the ARM register v shifted to the top, e.g. 0xc000 -> 0xc0000000\r
280// Otherwise the ARM register v is sign extended, e.g. 0xc000 -> 0xffffc000\r
281\r
282int EaRead(int a,int v,int ea,int size,int mask,int top)\r
283{\r
284 char text[32]="";\r
285 int shift=0;\r
286 \r
287 shift=32-(8<<size);\r
288\r
289 DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
290\r
291 if (ea<0x10)\r
292 {\r
293 int lsl=0,low=0,i;\r
294 if (size>=2||(size==0&&top)) {\r
a6785576 295 if(mask)\r
cc68a136 296 for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
a6785576 297 lsl=2-low; // Having a lsl #2 here saves one opcode\r
298 }\r
cc68a136 299\r
300 ot(";@ EaRead : Read register[r%d] into r%d:\n",a,v);\r
301\r
302 if (lsl>0) ot(" ldr%s r%d,[r7,r%d,lsl #%i]\n",Narm[size&3],v,a,lsl);\r
303 else if (lsl<0) ot(" ldr%s r%d,[r7,r%d,lsr #%i]\n",Narm[size&3],v,a,-lsl);\r
304 else ot(" ldr%s r%d,[r7,r%d]\n",Sarm[size&3],v,a);\r
305\r
306 if (top && shift) ot(" mov r%d,r%d,asl #%d\n",v,v,shift);\r
307\r
308 ot("\n"); return 0;\r
309 }\r
310\r
311 ot(";@ EaRead : Read '%s' (address in r%d) into r%d:\n",text,a,v);\r
312\r
313 if (ea==0x3c)\r
314 {\r
315 int asl=0;\r
316\r
317 if (top) asl=shift;\r
318\r
319 if (v!=a || asl) ot(" mov r%d,r%d,asl #%d\n",v,a,asl);\r
320 ot("\n"); return 0;\r
321 }\r
322\r
cfb3dfa0 323 if (ea>=0x3a && ea<=0x3b) MemHandler(2,size,a); // Fetch\r
324 else MemHandler(0,size,a); // Read\r
cc68a136 325\r
326 if (v!=0 || shift) {\r
327 if (shift) ot(" mov r%d,r0,asl #%d\n",v,shift);\r
328 else ot(" mov r%d,r0\n",v);\r
329 }\r
330 if (top==0 && shift) ot(" mov r%d,r%d,asr #%d\n",v,v,shift);\r
331\r
332 ot("\n"); return 0;\r
333}\r
334\r
335// Return 1 if we can read this ea\r
336int EaCanRead(int ea,int size)\r
337{\r
338 if (size<0)\r
339 {\r
340 // LEA:\r
341 // These don't make sense?:\r
342 if (ea< 0x10) return 0; // Register\r
343 if (ea==0x3c) return 0; // Immediate\r
344 if (ea>=0x18 && ea<0x28) return 0; // Pre/Post inc/dec An\r
345 }\r
346\r
347 if (ea<=0x3c) return 1;\r
348 return 0;\r
349}\r
350\r
351// ---------------------------------------------------------------------------\r
352// Write effective address (ARM Register 'a') with ARM register 'v'\r
353// Trashes r0-r3,r12,lr; 'a' can be 0 or 2+, 'v' can be 1 or higher\r
354// If a==0 and v==1 it's faster though.\r
355int EaWrite(int a,int v,int ea,int size,int mask,int top)\r
356{\r
357 char text[32]="";\r
358 int shift=0;\r
359\r
360 if(a == 1) { printf("Error! EaWrite a==1 !\n"); return 1; }\r
361\r
362 if (top) shift=32-(8<<size);\r
363\r
364 DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
365\r
366 if (ea<0x10)\r
367 {\r
368 int lsl=0,low=0,i;\r
369 if (size>=2||(size==0&&top)) {\r
a6785576 370 if(mask)\r
cc68a136 371 for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
a6785576 372 lsl=2-low; // Having a lsl #x here saves one opcode\r
373 }\r
cc68a136 374\r
375 ot(";@ EaWrite: r%d into register[r%d]:\n",v,a);\r
376 if (shift) ot(" mov r%d,r%d,asr #%d\n",v,v,shift);\r
377\r
378 if (lsl>0) ot(" str%s r%d,[r7,r%d,lsl #%i]\n",Narm[size&3],v,a,lsl);\r
379 else if (lsl<0) ot(" str%s r%d,[r7,r%d,lsr #%i]\n",Narm[size&3],v,a,-lsl);\r
380 else ot(" str%s r%d,[r7,r%d]\n",Narm[size&3],v,a);\r
381\r
382 ot("\n"); return 0;\r
383 }\r
384\r
385 ot(";@ EaWrite: Write r%d into '%s' (address in r%d):\n",v,text,a);\r
386\r
387 if (ea==0x3c) { ot("Error! Write EA=0x%x\n\n",ea); return 1; }\r
388\r
cc68a136 389 if (v!=1 || shift) ot(" mov r1,r%d,asr #%d\n",v,shift);\r
cc68a136 390\r
cfb3dfa0 391 MemHandler(1,size,a); // Call write handler\r
cc68a136 392\r
393 ot("\n"); return 0;\r
394}\r
395\r
396// Return 1 if we can write this ea\r
397int EaCanWrite(int ea)\r
398{\r
399 if (ea<=0x39) return 1; // 3b?\r
400 return 0;\r
401}\r
402// ---------------------------------------------------------------------------\r
403\r
404// Return 1 if EA is An reg\r
405int EaAn(int ea)\r
406{\r
407 if((ea&0x38)==8) return 1;\r
408 return 0;\r
409}\r
410\r