more MAME fixes, some optimization
[picodrive.git] / cpu / Cyclone / OpLogic.cpp
CommitLineData
cc68a136 1#include "app.h"\r
2\r
3// --------------------- Opcodes 0x0100+ ---------------------\r
4// Emit a Btst (Register) opcode 0000nnn1 ttaaaaaa\r
5int OpBtstReg(int op)\r
6{\r
7 int use=0;\r
8 int type=0,sea=0,tea=0;\r
9 int size=0;\r
10\r
11 type=(op>>6)&3; // Btst/Bchg/Bclr/Bset\r
12 // Get source and target EA\r
13 sea=(op>>9)&7;\r
14 tea=op&0x003f;\r
15 if (tea<0x10) size=2; // For registers, 32-bits\r
16\r
17 if ((tea&0x38)==0x08) return 1; // movep\r
18\r
19 // See if we can do this opcode:\r
20 if (EaCanRead(tea,0)==0) return 1;\r
21 if (type>0)\r
22 {\r
23 if (EaCanWrite(tea)==0) return 1;\r
24 }\r
25\r
26 use=OpBase(op);\r
27 use&=~0x0e00; // Use same handler for all registers\r
28 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
29\r
a6785576 30 OpStart(op,tea);\r
cc68a136 31\r
32 if(type==1||type==3) {\r
33 Cycles=8;\r
34 } else {\r
35 Cycles=type?8:4;\r
36 if(size>=2) Cycles+=2;\r
37 }\r
38\r
39 EaCalc (0,0x0e00,sea,0);\r
40 EaRead (0, 0,sea,0,0x0e00);\r
41 if (tea>=0x10)\r
42 ot(" and r10,r0,#7 ;@ mem - do mod 8\n");\r
43 else ot(" and r10,r0,#31 ;@ reg - do mod 32\n");\r
44 ot("\n");\r
45\r
46 EaCalc(11,0x003f,tea,size);\r
47 EaRead(11, 0,tea,size,0x003f);\r
48 ot(" mov r1,#1\n");\r
49 ot(" tst r0,r1,lsl r10 ;@ Do arithmetic\n");\r
50 ot(" bicne r9,r9,#0x40000000\n");\r
51 ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n");\r
52 ot("\n");\r
53\r
54 if (type>0)\r
55 {\r
56 if (type==1) ot(" eor r1,r0,r1,lsl r10 ;@ Toggle bit\n");\r
57 if (type==2) ot(" bic r1,r0,r1,lsl r10 ;@ Clear bit\n");\r
58 if (type==3) ot(" orr r1,r0,r1,lsl r10 ;@ Set bit\n");\r
59 ot("\n");\r
60 EaWrite(11, 1,tea,size,0x003f);\r
61 }\r
cfb3dfa0 62 OpEnd(tea);\r
cc68a136 63\r
64 return 0;\r
65}\r
66\r
67// --------------------- Opcodes 0x0800+ ---------------------\r
68// Emit a Btst/Bchg/Bclr/Bset (Immediate) opcode 00001000 ttaaaaaa nn\r
69int OpBtstImm(int op)\r
70{\r
71 int type=0,sea=0,tea=0;\r
72 int use=0;\r
73 int size=0;\r
74\r
75 type=(op>>6)&3;\r
76 // Get source and target EA\r
77 sea= 0x003c;\r
78 tea=op&0x003f;\r
79 if (tea<0x10) size=2; // For registers, 32-bits\r
80\r
81 // See if we can do this opcode:\r
82 if (EaCanRead(tea,0)==0||EaAn(tea)||tea==0x3c) return 1;\r
83 if (type>0)\r
84 {\r
85 if (EaCanWrite(tea)==0) return 1;\r
86 }\r
87\r
88 use=OpBase(op);\r
89 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
90\r
cfb3dfa0 91 OpStart(op,sea,tea);\r
cc68a136 92\r
93 ot(" mov r10,#1\n");\r
94 ot("\n");\r
95 EaCalc ( 0,0x0000,sea,0);\r
96 EaRead ( 0, 0,sea,0,0);\r
97 ot(" bic r9,r9,#0x40000000 ;@ Blank Z flag\n");\r
98 if (tea>=0x10)\r
99 ot(" and r0,r0,#7 ;@ mem - do mod 8\n");\r
100 else ot(" and r0,r0,#0x1F ;@ reg - do mod 32\n");\r
101 ot(" mov r10,r10,lsl r0 ;@ Make bit mask\n");\r
102 ot("\n");\r
103\r
104 if(type==1||type==3) {\r
105 Cycles=12;\r
106 } else {\r
107 Cycles=type?12:8;\r
108 if(size>=2) Cycles+=2;\r
109 }\r
110\r
111 EaCalc (11,0x003f,tea,size);\r
112 EaRead (11, 0,tea,size,0x003f);\r
113 ot(" tst r0,r10 ;@ Do arithmetic\n");\r
114 ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n");\r
115 ot("\n");\r
116\r
117 if (type>0)\r
118 {\r
119 if (type==1) ot(" eor r1,r0,r10 ;@ Toggle bit\n");\r
120 if (type==2) ot(" bic r1,r0,r10 ;@ Clear bit\n");\r
121 if (type==3) ot(" orr r1,r0,r10 ;@ Set bit\n");\r
122 ot("\n");\r
123 EaWrite(11, 1,tea,size,0x003f);\r
124 }\r
125\r
cfb3dfa0 126 OpEnd(sea,tea);\r
cc68a136 127\r
128 return 0;\r
129}\r
130\r
131// --------------------- Opcodes 0x4000+ ---------------------\r
132int OpNeg(int op)\r
133{\r
134 // 01000tt0 xxeeeeee (tt=negx/clr/neg/not, xx=size, eeeeee=EA)\r
135 int type=0,size=0,ea=0,use=0;\r
136\r
137 type=(op>>9)&3;\r
138 ea =op&0x003f;\r
139 size=(op>>6)&3; if (size>=3) return 1;\r
140\r
141 // See if we can do this opcode:\r
142 if (EaCanRead (ea,size)==0||EaAn(ea)) return 1;\r
143 if (EaCanWrite(ea )==0) return 1;\r
144\r
145 use=OpBase(op);\r
146 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
147\r
a6785576 148 OpStart(op,ea); Cycles=size<2?4:6;\r
cc68a136 149 if(ea >= 0x10) {\r
150 Cycles*=2;\r
a9a5a6e0 151#if CYCLONE_FOR_GENESIS\r
cc68a136 152 // This is same as in Starscream core, CLR uses only 6 cycles for memory EAs.\r
153 // May be this is similar case as with TAS opcode, but this time the dummy\r
154 // read is ignored somehow? Without this hack Fatal Rewind hangs even in Gens.\r
155 if(type==1&&size<2) Cycles-=2;\r
156#endif\r
157 }\r
158\r
159 EaCalc (10,0x003f,ea,size);\r
160\r
161 if (type!=1) EaRead (10,0,ea,size,0x003f); // Don't need to read for 'clr'\r
162 if (type==1) ot("\n");\r
163\r
164 if (type==0)\r
165 {\r
166 ot(";@ Negx:\n");\r
167 GetXBit(1);\r
168 if(size!=2) ot(" mov r0,r0,lsl #%i\n",size?16:24);\r
169 ot(" rscs r1,r0,#0 ;@ do arithmetic\n");\r
170 ot(" orr r3,r9,#0xb0000000 ;@ for old Z\n");\r
171 OpGetFlags(1,1,0);\r
172 if(size!=2) {\r
a6785576 173 ot(" movs r1,r1,asr #%i\n",size?16:24);\r
cc68a136 174 ot(" orreq r9,r9,#0x40000000 ;@ possily missed Z\n");\r
a6785576 175 }\r
176 ot(" andeq r9,r9,r3 ;@ fix Z\n");\r
cc68a136 177 ot("\n");\r
178 }\r
179\r
180 if (type==1)\r
181 {\r
182 ot(";@ Clear:\n");\r
183 ot(" mov r1,#0\n");\r
184 ot(" mov r9,#0x40000000 ;@ NZCV=0100\n");\r
185 ot("\n");\r
186 }\r
187\r
188 if (type==2)\r
189 {\r
190 ot(";@ Neg:\n");\r
191 if(size!=2) ot(" mov r0,r0,lsl #%i\n",size?16:24);\r
192 ot(" rsbs r1,r0,#0\n");\r
193 OpGetFlags(1,1);\r
194 if(size!=2) ot(" mov r1,r1,asr #%i\n",size?16:24);\r
195 ot("\n");\r
196 }\r
197\r
198 if (type==3)\r
199 {\r
200 ot(";@ Not:\n");\r
201 ot(" mvn r1,r0\n");\r
202 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
203 OpGetFlags(0,0);\r
204 ot("\n");\r
205 }\r
206\r
207 EaWrite(10, 1,ea,size,0x003f);\r
208\r
cfb3dfa0 209 OpEnd(ea);\r
cc68a136 210\r
211 return 0;\r
212}\r
213\r
214// --------------------- Opcodes 0x4840+ ---------------------\r
215// Swap, 01001000 01000nnn swap Dn\r
216int OpSwap(int op)\r
217{\r
218 int ea=0,use=0;\r
219\r
220 ea=op&7;\r
221 use=op&~0x0007; // Use same opcode for all An\r
222\r
223 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
224\r
225 OpStart(op); Cycles=4;\r
226\r
227 EaCalc (10,0x0007,ea,2,1);\r
228 EaRead (10, 0,ea,2,0x0007,1);\r
229\r
230 ot(" mov r1,r0,ror #16\n");\r
231 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
232 OpGetFlags(0,0);\r
233\r
234 EaWrite(10, 1,8,2,0x0007,1);\r
235\r
236 OpEnd();\r
237\r
238 return 0;\r
239}\r
240\r
241// --------------------- Opcodes 0x4a00+ ---------------------\r
242// Emit a Tst opcode, 01001010 xxeeeeee\r
243int OpTst(int op)\r
244{\r
245 int sea=0;\r
246 int size=0,use=0;\r
247\r
248 sea=op&0x003f;\r
249 size=(op>>6)&3; if (size>=3) return 1;\r
250\r
251 // See if we can do this opcode:\r
252 if (EaCanWrite(sea)==0||EaAn(sea)) return 1;\r
253\r
254 use=OpBase(op);\r
255 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
256\r
a6785576 257 OpStart(op,sea); Cycles=4;\r
cc68a136 258\r
259 EaCalc ( 0,0x003f,sea,size,1);\r
260 EaRead ( 0, 0,sea,size,0x003f,1);\r
261\r
262 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");\r
263 ot(" mrs r9,cpsr ;@ r9=flags\n");\r
264 ot("\n");\r
265\r
cfb3dfa0 266 OpEnd(sea);\r
cc68a136 267 return 0;\r
268}\r
269\r
270// --------------------- Opcodes 0x4880+ ---------------------\r
271// Emit an Ext opcode, 01001000 1x000nnn\r
272int OpExt(int op)\r
273{\r
274 int ea=0;\r
275 int size=0,use=0;\r
276 int shift=0;\r
277\r
278 ea=op&0x0007;\r
279 size=(op>>6)&1;\r
280 shift=32-(8<<size);\r
281\r
282 use=OpBase(op);\r
283 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
284\r
285 OpStart(op); Cycles=4;\r
286\r
287 EaCalc (10,0x0007,ea,size+1);\r
288 EaRead (10, 0,ea,size+1,0x0007);\r
289\r
290 ot(" mov r0,r0,asl #%d\n",shift);\r
291 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");\r
292 ot(" mrs r9,cpsr ;@ r9=flags\n");\r
293 ot(" mov r1,r0,asr #%d\n",shift);\r
294 ot("\n");\r
295\r
296 EaWrite(10, 1,ea,size+1,0x0007);\r
297\r
298 OpEnd();\r
299 return 0;\r
300}\r
301\r
302// --------------------- Opcodes 0x50c0+ ---------------------\r
303// Emit a Set cc opcode, 0101cccc 11eeeeee\r
304int OpSet(int op)\r
305{\r
306 int cc=0,ea=0;\r
307 int size=0,use=0;\r
308 char *cond[16]=\r
309 {\r
310 "al","", "hi","ls","cc","cs","ne","eq",\r
311 "vc","vs","pl","mi","ge","lt","gt","le"\r
312 };\r
313\r
314 cc=(op>>8)&15;\r
315 ea=op&0x003f;\r
316\r
317 if ((ea&0x38)==0x08) return 1; // dbra, not scc\r
318 \r
319 // See if we can do this opcode:\r
320 if (EaCanWrite(ea)==0) return 1;\r
321\r
322 use=OpBase(op);\r
323 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
324\r
a6785576 325 OpStart(op,ea); Cycles=8;\r
cc68a136 326 if (ea<8) Cycles=4;\r
327\r
328 ot(" mov r1,#0\n");\r
329\r
330 if (cc!=1)\r
331 {\r
332 ot(";@ Is the condition true?\n");\r
333 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");\r
334 ot(" msr cpsr_flg,r9 ;@ ARM flags = 68000 flags\n");\r
335 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");\r
336 ot(" mvn%s r1,r1\n",cond[cc]);\r
337 }\r
338\r
339 if (cc!=1 && ea<8) ot(" sub%s r5,r5,#2 ;@ Extra cycles\n",cond[cc]);\r
340 ot("\n");\r
341\r
342 EaCalc (0,0x003f, ea,size);\r
343 EaWrite(0, 1, ea,size,0x003f);\r
344\r
cfb3dfa0 345 OpEnd(ea);\r
cc68a136 346 return 0;\r
347}\r
348\r
349// Emit a Asr/Lsr/Roxr/Ror opcode\r
350static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)\r
351{\r
352 char pct[8]=""; // count\r
353 int shift=32-(8<<size);\r
354\r
355 if (count>=1) sprintf(pct,"#%d",count); // Fixed count\r
356\r
357 if (usereg)\r
358 {\r
359 ot(";@ Use Dn for count:\n");\r
360 ot(" and r2,r8,#7<<9\n");\r
361 ot(" ldr r2,[r7,r2,lsr #7]\n");\r
362 ot(" and r2,r2,#63\n");\r
363 ot("\n");\r
364 strcpy(pct,"r2");\r
365 }\r
366 else if (count<0)\r
367 {\r
368 ot(" mov r2,r8,lsr #9 ;@ Get 'n'\n");\r
369 ot(" and r2,r2,#7\n\n"); strcpy(pct,"r2");\r
370 }\r
371\r
372 // Take 2*n cycles:\r
373 if (count<0) ot(" sub r5,r5,r2,asl #1 ;@ Take 2*n cycles\n\n");\r
374 else Cycles+=count<<1;\r
375\r
376 if (type<2)\r
377 {\r
378 // Asr/Lsr\r
379 if (dir==0 && size<2)\r
380 {\r
381 ot(";@ For shift right, use loworder bits for the operation:\n");\r
382 ot(" mov r0,r0,%s #%d\n",type?"lsr":"asr",32-(8<<size));\r
383 ot("\n");\r
384 }\r
385\r
386 if (type==0 && dir) ot(" mov r3,r0 ;@ save old value for V flag calculation\n");\r
387\r
388 ot(";@ Shift register:\n");\r
389 if (type==0) ot(" movs r0,r0,%s %s\n",dir?"asl":"asr",pct);\r
390 if (type==1) ot(" movs r0,r0,%s %s\n",dir?"lsl":"lsr",pct);\r
391\r
392 if (dir==0 && size<2)\r
393 {\r
394 ot(";@ restore after right shift:\n");\r
395 ot(" mov r0,r0,lsl #%d\n",32-(8<<size));\r
396 ot("\n");\r
397 }\r
398\r
399 OpGetFlags(0,0);\r
400 if (usereg) { // store X only if count is not 0\r
401 ot(" cmp %s,#0 ;@ shifting by 0?\n",pct);\r
402 ot(" biceq r9,r9,#0x20000000 ;@ if so, clear carry\n");\r
403 ot(" movne r1,r9,lsr #28\n");\r
404 ot(" strneb r1,[r7,#0x45] ;@ else Save X bit\n");\r
405 } else {\r
406 // count will never be 0 if we use immediate\r
407 ot(" mov r1,r9,lsr #28\n");\r
408 ot(" strb r1,[r7,#0x45] ;@ Save X bit\n");\r
409 }\r
410\r
411 if (type==0 && dir) {\r
412 ot(";@ calculate V flag (set if sign bit changes at anytime):\n");\r
413 ot(" mov r1,#0x80000000\n");\r
414 ot(" ands r3,r3,r1,asr %s\n", pct);\r
415 ot(" cmpne r3,r1,asr %s\n", pct);\r
416 ot(" biceq r9,r9,#0x10000000\n");\r
417 ot(" orrne r9,r9,#0x10000000\n");\r
418 }\r
419\r
420 ot("\n");\r
421 }\r
422\r
423 // --------------------------------------\r
424 if (type==2)\r
425 {\r
426 int wide=8<<size;\r
427\r
428 // Roxr\r
429 if(count == 1) {\r
430 if(dir==0) {\r
431 if(size!=2) {\r
a6785576 432 ot(" orr r0,r0,r0,lsr #%i\n", size?16:24);\r
433 ot(" bic r0,r0,#0x%x\n", 1<<(32-wide));\r
434 }\r
cc68a136 435 GetXBit(0);\r
436 ot(" movs r0,r0,rrx\n");\r
437 OpGetFlags(0,1);\r
438 } else {\r
439 ot(" ldrb r3,[r7,#0x45]\n");\r
440 ot(" movs r0,r0,lsl #1\n");\r
441 OpGetFlags(0,1);\r
442 ot(" tst r3,#2\n");\r
443 ot(" orrne r0,r0,#0x%x\n", 1<<(32-wide));\r
444 ot(" bicne r9,r9,#0x40000000 ;@ clear Z in case it got there\n");\r
445 }\r
446 ot(" bic r9,r9,#0x10000000 ;@ make suve V is clear\n");\r
447 return 0;\r
448 }\r
449\r
450 if (usereg)\r
451 {\r
452 ot(";@ Reduce r2 until <0:\n");\r
453 ot("Reduce_%.4x%s\n",op,ms?"":":");\r
454 ot(" subs r2,r2,#%d\n",wide+1);\r
455 ot(" bpl Reduce_%.4x\n",op);\r
456 ot(" adds r2,r2,#%d ;@ Now r2=0-%d\n",wide+1,wide);\r
457 ot(" beq norotx%.4x\n",op);\r
458 ot("\n");\r
459 }\r
460\r
461 if (usereg||count < 0)\r
462 {\r
463 if (dir) ot(" rsb r2,r2,#%d ;@ Reverse direction\n",wide+1);\r
464 }\r
465 else\r
466 {\r
467 if (dir) ot(" mov r2,#%d ;@ Reversed\n",wide+1-count);\r
468 else ot(" mov r2,#%d\n",count);\r
469 }\r
470\r
471 if (shift) ot(" mov r0,r0,lsr #%d ;@ Shift down\n",shift);\r
472\r
473 ot(";@ Rotate bits:\n");\r
474 ot(" mov r3,r0,lsr r2 ;@ Get right part\n");\r
475 ot(" rsbs r2,r2,#%d ;@ should also clear ARM V\n",wide+1);\r
476 ot(" movs r0,r0,lsl r2 ;@ Get left part\n");\r
477 ot(" orr r0,r3,r0 ;@ r0=Rotated value\n");\r
478\r
479 ot(";@ Insert X bit into r2-1:\n");\r
480 ot(" ldrb r3,[r7,#0x45]\n");\r
481 ot(" sub r2,r2,#1\n");\r
482 ot(" and r3,r3,#2\n");\r
483 ot(" mov r3,r3,lsr #1\n");\r
484 ot(" orr r0,r0,r3,lsl r2\n");\r
485 ot("\n");\r
486\r
487 if (shift) ot(" movs r0,r0,lsl #%d ;@ Shift up and get correct NC flags\n",shift);\r
488 OpGetFlags(0,!usereg);\r
489 if (!shift) {\r
490 ot(" tst r0,r0\n");\r
491 ot(" bicne r9,r9,#0x40000000 ;@ make sure we didn't mess Z\n");\r
492 }\r
493 if (usereg) { // store X only if count is not 0\r
494 ot(" mov r2,r9,lsr #28\n");\r
495 ot(" strb r2,[r7,#0x45] ;@ if not 0, Save X bit\n");\r
496 ot(" b nozerox%.4x\n",op);\r
497 ot("norotx%.4x%s\n",op,ms?"":":");\r
498 ot(" ldrb r2,[r7,#0x45]\n");\r
499 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");\r
500 OpGetFlags(0,0);\r
501 ot(" and r2,r2,#2\n");\r
502 ot(" orr r9,r9,r2,lsl #28 ;@ C = old_X\n");\r
503 ot("nozerox%.4x%s\n",op,ms?"":":");\r
504 }\r
505\r
506 ot("\n");\r
507 }\r
508\r
509 // --------------------------------------\r
510 if (type==3)\r
511 {\r
512 // Ror\r
513 if (size<2)\r
514 {\r
515 ot(";@ Mirror value in whole 32 bits:\n");\r
516 if (size<=0) ot(" orr r0,r0,r0,lsr #8\n");\r
517 if (size<=1) ot(" orr r0,r0,r0,lsr #16\n");\r
518 ot("\n");\r
519 }\r
520\r
521 ot(";@ Rotate register:\n");\r
522 if (count<0)\r
523 {\r
524 if (dir) ot(" rsbs %s,%s,#32\n",pct,pct);\r
525 ot(" movs r0,r0,ror %s\n",pct);\r
526 }\r
527 else\r
528 {\r
529 int ror=count;\r
530 if (dir) ror=32-ror;\r
531 if (ror&31) ot(" movs r0,r0,ror #%d\n",ror);\r
532 }\r
533\r
534 OpGetFlags(0,0);\r
535 if (!dir) ot(" bic r9,r9,#0x10000000 ;@ make suve V is clear\n");\r
536 if (dir)\r
537 {\r
538 ot(";@ Get carry bit from bit 0:\n");\r
539 if (usereg)\r
540 {\r
541 ot(" cmp %s,#32 ;@ rotating by 0?\n",pct);\r
542 ot(" tstne r0,#1 ;@ no, check bit 0\n");\r
543 }\r
544 else\r
545 ot(" tst r0,#1\n");\r
546 ot(" orrne r9,r9,#0x20000000\n");\r
547 ot(" biceq r9,r9,#0x20000000\n");\r
548 }\r
549 else if (usereg)\r
550 {\r
551 // if we rotate something by 0, ARM doesn't clear C\r
552 // so we need to detect that\r
553 ot(" cmp %s,#0\n",pct);\r
554 ot(" biceq r9,r9,#0x20000000\n");\r
555 }\r
556 ot("\n");\r
557\r
558 }\r
559 // --------------------------------------\r
560 \r
561 return 0;\r
562}\r
563\r
564// Emit a Asr/Lsr/Roxr/Ror opcode - 1110cccd xxuttnnn\r
565// (ccc=count, d=direction(r,l) xx=size extension, u=use reg for count, tt=type, nnn=register Dn)\r
566int OpAsr(int op)\r
567{\r
568 int ea=0,use=0;\r
569 int count=0,dir=0;\r
570 int size=0,usereg=0,type=0;\r
571\r
572 ea=0;\r
573 count =(op>>9)&7;\r
574 dir =(op>>8)&1;\r
575 size =(op>>6)&3;\r
576 if (size>=3) return 1; // use OpAsrEa()\r
577 usereg=(op>>5)&1;\r
578 type =(op>>3)&3;\r
579\r
580 if (usereg==0) count=((count-1)&7)+1; // because ccc=000 means 8\r
581\r
582 // Use the same opcode for target registers:\r
583 use=op&~0x0007;\r
584\r
585 // As long as count is not 8, use the same opcode for all shift counts::\r
586 if (usereg==0 && count!=8 && !(count==1&&type==2)) { use|=0x0e00; count=-1; }\r
587 if (usereg) { use&=~0x0e00; count=-1; } // Use same opcode for all Dn\r
588\r
589 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
590\r
591 OpStart(op); Cycles=size<2?6:8;\r
592\r
593 EaCalc(10,0x0007, ea,size,1);\r
594 EaRead(10, 0, ea,size,0x0007,1);\r
595\r
596 EmitAsr(op,type,dir,count, size,usereg);\r
597\r
598 EaWrite(10, 0, ea,size,0x0007,1);\r
599\r
600 OpEnd();\r
601\r
602 return 0;\r
603}\r
604\r
605// Asr/Lsr/Roxr/Ror etc EA - 11100ttd 11eeeeee \r
606int OpAsrEa(int op)\r
607{\r
608 int use=0,type=0,dir=0,ea=0,size=1;\r
609\r
610 type=(op>>9)&3;\r
611 dir =(op>>8)&1;\r
612 ea = op&0x3f;\r
613\r
614 if (ea<0x10) return 1;\r
615 // See if we can do this opcode:\r
616 if (EaCanRead(ea,0)==0) return 1;\r
617 if (EaCanWrite(ea)==0) return 1;\r
618\r
619 use=OpBase(op);\r
620 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
621\r
a6785576 622 OpStart(op,ea); Cycles=6; // EmitAsr() will add 2\r
cc68a136 623\r
624 EaCalc (10,0x003f,ea,size,1);\r
625 EaRead (10, 0,ea,size,0x003f,1);\r
626\r
627 EmitAsr(op,type,dir,1,size,0);\r
628\r
629 EaWrite(10, 0,ea,size,0x003f,1);\r
630\r
cfb3dfa0 631 OpEnd(ea);\r
cc68a136 632 return 0;\r
633}\r
634\r
c008977e 635int OpTas(int op, int gen_special)\r
cc68a136 636{\r
637 int ea=0;\r
638 int use=0;\r
639\r
640 ea=op&0x003f;\r
641\r
642 // See if we can do this opcode:\r
643 if (EaCanWrite(ea)==0 || EaAn(ea)) return 1;\r
644\r
645 use=OpBase(op);\r
646 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
647\r
a6785576 648 if (!gen_special) OpStart(op,ea);\r
c008977e 649 else\r
650 ot("Op%.4x_%s\n", op, ms?"":":");\r
651\r
652 Cycles=4;\r
cc68a136 653 if(ea>=8) Cycles+=10;\r
654\r
655 EaCalc (10,0x003f,ea,0,1);\r
656 EaRead (10, 1,ea,0,0x003f,1);\r
657\r
658 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
659 OpGetFlags(0,0);\r
660 ot("\n");\r
661\r
662#if CYCLONE_FOR_GENESIS\r
663 // the original Sega hardware ignores write-back phase (to memory only)\r
c008977e 664 if (ea < 0x10 || gen_special) {\r
cc68a136 665#endif\r
666 ot(" orr r1,r1,#0x80000000 ;@ set bit7\n");\r
667\r
668 EaWrite(10, 1,ea,0,0x003f,1);\r
669#if CYCLONE_FOR_GENESIS\r
670 }\r
671#endif\r
672\r
cfb3dfa0 673 OpEnd(ea);\r
c008977e 674\r
a9a5a6e0 675#if (CYCLONE_FOR_GENESIS == 2)\r
c008977e 676 if (!gen_special && ea >= 0x10) {\r
677 OpTas(op, 1);\r
678 }\r
679#endif\r
680\r
cc68a136 681 return 0;\r
682}\r
683\r