2 // This file is part of the Cyclone 68000 Emulator
\r
4 // Copyright (c) 2011 FinalDave (emudave (at) gmail.com)
\r
6 // This code is licensed under the GNU General Public License version 2.0 and the MAME License.
\r
7 // You can choose the license that has the most advantages for you.
\r
9 // SVN repository can be found at http://code.google.com/p/cyclone68000/
\r
13 // --------------------- Opcodes 0x0100+ ---------------------
\r
14 // Emit a Btst (Register) opcode 0000nnn1 00aaaaaa
\r
15 int OpBtstReg(int op)
\r
18 int type=0,sea=0,tea=0;
\r
22 // Get source and target EA
\r
25 if (tea<0x10) size=2; // For registers, 32-bits
\r
27 if ((tea&0x38)==0x08) return 1; // movep
\r
29 // See if we can do this opcode:
\r
30 if (EaCanRead(tea,0)==0) return 1;
\r
33 if (EaCanWrite(tea)==0) return 1;
\r
37 use&=~0x0e00; // Use same handler for all registers
\r
38 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
40 OpStart(op); Cycles=4;
\r
41 if (tea<0x10) Cycles+=2;
\r
42 if (type>0) Cycles+=4;
\r
44 ot(" mov r10,#1\n");
\r
46 EaCalc (0,0x0e00,sea,0);
\r
47 EaRead (0, 0,sea,0);
\r
48 ot(" bic r9,r9,#0x40000000 ;@ Blank Z flag\n");
\r
49 ot(" mov r10,r10,lsl r0 ;@ Make bit mask\n");
\r
52 EaCalc(11,0x003f,tea,size);
\r
53 EaRead(11, 0,tea,size);
\r
54 ot(" tst r0,r10 ;@ Do arithmetic\n");
\r
55 ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n");
\r
60 if (type==1) ot(" eor r1,r0,r10 ;@ Toggle bit\n");
\r
61 if (type==2) ot(" bic r1,r0,r10 ;@ Clear bit\n");
\r
62 if (type==3) ot(" orr r1,r0,r10 ;@ Set bit\n");
\r
64 EaWrite(11, 1,tea,size);
\r
71 // --------------------- Opcodes 0x0800+ ---------------------
\r
72 // Emit a Btst/Bchg/Bclr/Bset (Immediate) opcode 00001000 ttaaaaaa nn
\r
73 int OpBtstImm(int op)
\r
75 int type=0,sea=0,tea=0;
\r
80 // Get source and target EA
\r
83 if (tea<0x10) size=2; // For registers, 32-bits
\r
85 // See if we can do this opcode:
\r
86 if (EaCanRead(tea,0)==0) return 1;
\r
89 if (EaCanWrite(tea)==0) return 1;
\r
93 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
95 OpStart(op); Cycles=4;
\r
96 if (type<3 && tea<0x10) Cycles+=2;
\r
97 if (type>0) Cycles+=4;
\r
99 ot(" mov r10,#1\n");
\r
101 EaCalc ( 0,0x0000,sea,0);
\r
102 EaRead ( 0, 0,sea,0);
\r
103 ot(" bic r9,r9,#0x40000000 ;@ Blank Z flag\n");
\r
104 ot(" mov r10,r10,lsl r0 ;@ Make bit mask\n");
\r
107 EaCalc (11,0x003f,tea,size);
\r
108 EaRead (11, 0,tea,size);
\r
109 ot(" tst r0,r10 ;@ Do arithmetic\n");
\r
110 ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n");
\r
115 if (type==1) ot(" eor r1,r0,r10 ;@ Toggle bit\n");
\r
116 if (type==2) ot(" bic r1,r0,r10 ;@ Clear bit\n");
\r
117 if (type==3) ot(" orr r1,r0,r10 ;@ Set bit\n");
\r
119 EaWrite(11, 1,tea,size);
\r
127 // --------------------- Opcodes 0x4000+ ---------------------
\r
130 // 01000tt0 xxeeeeee (tt=negx/clr/neg/not, xx=size, eeeeee=EA)
\r
131 int type=0,size=0,ea=0,use=0;
\r
135 size=(op>>6)&3; if (size>=3) return 1;
\r
139 case 1: case 2: case 3: break;
\r
140 default: return 1; // todo
\r
143 // See if we can do this opcode:
\r
144 if (EaCanRead (ea,size)==0) return 1;
\r
145 if (EaCanWrite(ea )==0) return 1;
\r
148 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
150 OpStart(op); Cycles=size<2?4:6;
\r
152 EaCalc (10,0x003f,ea,size);
\r
154 if (type!=1) EaRead (10,0,ea,size); // Don't need to read for 'clr'
\r
155 if (type==1) ot("\n");
\r
160 ot(" mov r1,#0\n");
\r
161 ot(" mov r9,#0x40000000 ;@ NZCV=0100\n");
\r
168 ot(" rsbs r1,r0,#0\n");
\r
176 ot(" mvn r1,r0\n");
\r
177 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
\r
182 EaWrite(10, 1,ea,size);
\r
189 // --------------------- Opcodes 0x4840+ ---------------------
\r
190 // Swap, 01001000 01000nnn swap Dn
\r
196 use=op&~0x0007; // Use same opcode for all An
\r
198 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
200 OpStart(op); Cycles=4;
\r
202 EaCalc (10,0x0007,ea,2);
\r
203 EaRead (10, 0,ea,2);
\r
205 ot(" mov r1,r0,ror #16\n");
\r
206 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
\r
209 EaWrite(10, 1,8,2);
\r
216 // --------------------- Opcodes 0x4a00+ ---------------------
\r
217 // Emit a Tst opcode, 01001010 xxeeeeee
\r
224 size=(op>>6)&3; if (size>=3) return 1;
\r
226 // See if we can do this opcode:
\r
227 if (EaCanWrite(sea)==0) return 1;
\r
230 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
232 OpStart(op); Cycles=4;
\r
234 EaCalc ( 0,0x003f,sea,size);
\r
235 EaRead ( 0, 0,sea,size);
\r
237 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");
\r
238 ot(" mrs r9,cpsr ;@ r9=flags\n");
\r
245 // --------------------- Opcodes 0x4880+ ---------------------
\r
246 // Emit an Ext opcode, 01001000 1x000nnn
\r
255 shift=32-(8<<size);
\r
258 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
260 OpStart(op); Cycles=4;
\r
262 EaCalc (10,0x0007,ea,size+1);
\r
263 EaRead (10, 0,ea,size+1);
\r
265 ot(" mov r0,r0,asl #%d\n",shift);
\r
266 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");
\r
267 ot(" mrs r9,cpsr ;@ r9=flags\n");
\r
268 ot(" mov r1,r0,asr #%d\n",shift);
\r
271 EaWrite(10, 1,ea,size+1);
\r
277 // --------------------- Opcodes 0x50c0+ ---------------------
\r
278 // Emit a Set cc opcode, 0101cccc 11eeeeee
\r
285 "al","", "hi","ls","cc","cs","ne","eq",
\r
286 "vc","vs","pl","mi","ge","lt","gt","le"
\r
292 if ((ea&0x38)==0x08) return 1; // dbra, not scc
\r
294 // See if we can do this opcode:
\r
295 if (EaCanWrite(ea)==0) return 1;
\r
298 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
300 OpStart(op); Cycles=8;
\r
302 if (ea<0x10) Cycles=4;
\r
304 ot(" mov r1,#0\n");
\r
308 ot(";@ Is the condition true?\n");
\r
309 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");
\r
310 ot(" msr cpsr_flg,r9 ;@ ARM flags = 68000 flags\n");
\r
311 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");
\r
312 ot(" mvn%s r1,r1\n",cond[cc]);
\r
315 if (ea<0x10) ot(" sub%s r5,r5,#2 ;@ Extra cycles\n",cond[cc]);
\r
318 EaCalc (0,0x003f, ea,size);
\r
319 EaWrite(0, 1, ea,size);
\r
325 // Emit a Asr/Lsr/Roxr/Ror opcode
\r
326 static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
\r
329 int shift=32-(8<<size);
\r
331 if (count>=1) sprintf(pct,"#%d",count); // Fixed count
\r
335 ot(" mov r2,r8,lsr #9 ;@ Get 'n'\n");
\r
336 ot(" and r2,r2,#7\n\n"); strcpy(pct,"r2");
\r
341 ot(";@ Use Dn for count:\n");
\r
342 ot(" ldr r2,[r7,r2,lsl #2]\n");
\r
343 ot(" and r2,r2,#63\n");
\r
347 // Take 2*n cycles:
\r
348 if (count<0) ot(" sub r5,r5,r2,asl #1 ;@ Take 2*n cycles\n\n");
\r
349 else Cycles+=count<<1;
\r
354 if (dir==0 && size<2)
\r
356 ot(";@ For shift right, also copy to lowest bits (to get carry bit):\n");
\r
357 ot(" orr r0,r0,r0,lsr #%d\n",32-(8<<size));
\r
361 ot(";@ Shift register:\n");
\r
362 if (type==0) ot(" movs r0,r0,%s %s\n",dir?"asl":"asr",pct);
\r
363 if (type==1) ot(" movs r0,r0,%s %s\n",dir?"lsl":"lsr",pct);
\r
369 ot(";@ Check if result is zero:\n");
\r
370 ot(" movs r2,r0,lsr #%d\n",shift);
\r
371 ot(" orreq r9,r9,#0x40000000\n");
\r
376 // --------------------------------------
\r
382 if (shift) ot(" mov r0,r0,lsr #%d ;@ Shift down\n",shift);
\r
384 ot(";@ Rotate register through X:\n");
\r
385 if (strcmp("r2",pct)!=0) { ot(" mov r2,%s\n",pct); strcpy(pct,"r2"); } // Get into register
\r
389 ot(";@ Reduce r2 until <0:\n");
\r
390 ot("Reduce_%.4x%s\n",op,ms?"":":");
\r
391 ot(" subs r2,r2,#%d\n",wide+1);
\r
392 ot(" bpl Reduce_%.4x\n",op);
\r
393 ot(" add r2,r2,#%d ;@ Now r2=0-%d\n",wide+1,wide);
\r
397 if (dir) ot(" rsb r2,r2,#%d ;@ Reverse direction\n",wide+1);
\r
399 ot(";@ Rotate bits:\n");
\r
400 ot(" mov r3,r0,lsr r2 ;@ Get right part\n");
\r
401 ot(" rsb r2,r2,#%d\n",wide+1);
\r
402 ot(" movs r0,r0,lsl r2 ;@ Get left part\n");
\r
403 ot(" orr r0,r3,r0 ;@ r0=Rotated value\n");
\r
405 ot(";@ Insert X bit into r2-1:\n");
\r
406 ot(" ldrb r3,[r7,#0x45]\n");
\r
407 ot(" sub r2,r2,#1\n");
\r
408 ot(" and r3,r3,#2\n");
\r
409 ot(" mov r3,r3,lsr #1\n");
\r
410 ot(" orr r0,r0,r3,lsl r2\n");
\r
413 if (shift) ot(" movs r0,r0,lsl #%d ;@ Shift up and get correct NC flags\n",shift);
\r
418 // --------------------------------------
\r
424 ot(";@ Mirror value in whole 32 bits:\n");
\r
425 if (size<=0) ot(" orr r0,r0,r0,lsr #8\n");
\r
426 if (size<=1) ot(" orr r0,r0,r0,lsr #16\n");
\r
430 ot(";@ Rotate register:\n");
\r
433 if (dir) ot(" rsb r2,%s,#32\n",pct);
\r
434 ot(" movs r0,r0,ror %s\n",pct);
\r
439 if (dir) ror=32-ror;
\r
440 if (ror&31) ot(" movs r0,r0,ror #%d\n",ror);
\r
445 ot(";@ Get carry bit from bit 0:\n");
\r
446 ot(" mov r9,#0\n");
\r
447 ot(" ands r2,r0,#1\n");
\r
448 ot(" orrne r9,r9,#0x20000000\n");
\r
457 // --------------------------------------
\r
462 // Emit a Asr/Lsr/Roxr/Ror opcode - 1110cccd xxuttnnn
\r
463 // (ccc=count, d=direction xx=size extension, u=use reg for count, tt=type, nnn=register Dn)
\r
468 int size=0,usereg=0,type=0;
\r
474 if (size>=3) return 1; // todo Asr EA
\r
478 if (usereg==0) count=((count-1)&7)+1; // because ccc=000 means 8
\r
480 // Use the same opcode for target registers:
\r
483 // As long as count is not 8, use the same opcode for all shift counts::
\r
484 if (usereg==0 && count!=8) { use|=0x0e00; count=-1; }
\r
485 if (usereg) { use&=~0x0e00; count=-1; } // Use same opcode for all Dn
\r
487 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
489 OpStart(op); Cycles=size<2?6:8;
\r
491 EaCalc(10,0x0007, ea,size);
\r
492 EaRead(10, 0, ea,size,1);
\r
494 EmitAsr(op,type,dir,count, size,usereg);
\r
496 EaWrite(10, 0, ea,size,1);
\r
503 // Asr/l/Ror/l etc EA - 11100ttd 11eeeeee
\r
504 int OpAsrEa(int op)
\r
506 int use=0,type=0,dir=0,ea=0,size=1;
\r
512 if (ea<0x10) return 1;
\r
513 // See if we can do this opcode:
\r
514 if (EaCanRead(ea,0)==0) return 1;
\r
515 if (EaCanWrite(ea)==0) return 1;
\r
518 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
520 OpStart(op); Cycles=8;
\r
522 EaCalc (10,0x003f,ea,size);
\r
523 EaRead (10, 0,ea,size,1);
\r
525 EmitAsr(op,type,dir,1, size,0);
\r
527 ot(";@ Save shifted value back to EA:\n");
\r
528 ot(" mov r1,r0\n");
\r
529 EaWrite(10, 1,ea,size,1);
\r