3 // --------------------- Opcodes 0x0100+ ---------------------
\r
4 // Emit a Btst (Register) opcode 0000nnn1 00aaaaaa
\r
5 int OpBtstReg(int op)
\r
8 int type=0,sea=0,tea=0;
\r
12 // Get source and target EA
\r
15 if (tea<0x10) size=2; // For registers, 32-bits
\r
17 if ((tea&0x38)==0x08) return 1; // movep
\r
19 // See if we can do this opcode:
\r
20 if (EaCanRead(tea,0)==0) return 1;
\r
23 if (EaCanWrite(tea)==0) return 1;
\r
27 use&=~0x0e00; // Use same handler for all registers
\r
28 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
30 OpStart(op); Cycles=4;
\r
31 if (tea<0x10) Cycles+=2;
\r
32 if (type>0) Cycles+=4;
\r
34 ot(" mov r10,#1\n");
\r
36 EaCalc (0,0x0e00,sea,0);
\r
37 EaRead (0, 0,sea,0);
\r
38 ot(" bic r9,r9,#0x40000000 ;@ Blank Z flag\n");
\r
39 ot(" mov r10,r10,lsl r0 ;@ Make bit mask\n");
\r
42 EaCalc(11,0x003f,tea,size);
\r
43 EaRead(11, 0,tea,size);
\r
44 ot(" tst r0,r10 ;@ Do arithmetic\n");
\r
45 ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n");
\r
50 if (type==1) ot(" eor r1,r0,r10 ;@ Toggle bit\n");
\r
51 if (type==2) ot(" bic r1,r0,r10 ;@ Clear bit\n");
\r
52 if (type==3) ot(" orr r1,r0,r10 ;@ Set bit\n");
\r
54 EaWrite(11, 1,tea,size);
\r
61 // --------------------- Opcodes 0x0800+ ---------------------
\r
62 // Emit a Btst/Bchg/Bclr/Bset (Immediate) opcode 00001000 ttaaaaaa nn
\r
63 int OpBtstImm(int op)
\r
65 int type=0,sea=0,tea=0;
\r
70 // Get source and target EA
\r
73 if (tea<0x10) size=2; // For registers, 32-bits
\r
75 // See if we can do this opcode:
\r
76 if (EaCanRead(tea,0)==0) return 1;
\r
79 if (EaCanWrite(tea)==0) return 1;
\r
83 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
85 OpStart(op); Cycles=4;
\r
86 if (type<3 && tea<0x10) Cycles+=2;
\r
87 if (type>0) Cycles+=4;
\r
89 ot(" mov r10,#1\n");
\r
91 EaCalc ( 0,0x0000,sea,0);
\r
92 EaRead ( 0, 0,sea,0);
\r
93 ot(" bic r9,r9,#0x40000000 ;@ Blank Z flag\n");
\r
94 ot(" mov r10,r10,lsl r0 ;@ Make bit mask\n");
\r
97 EaCalc (11,0x003f,tea,size);
\r
98 EaRead (11, 0,tea,size);
\r
99 ot(" tst r0,r10 ;@ Do arithmetic\n");
\r
100 ot(" orreq r9,r9,#0x40000000 ;@ Get Z flag\n");
\r
105 if (type==1) ot(" eor r1,r0,r10 ;@ Toggle bit\n");
\r
106 if (type==2) ot(" bic r1,r0,r10 ;@ Clear bit\n");
\r
107 if (type==3) ot(" orr r1,r0,r10 ;@ Set bit\n");
\r
109 EaWrite(11, 1,tea,size);
\r
117 // --------------------- Opcodes 0x4000+ ---------------------
\r
120 // 01000tt0 xxeeeeee (tt=negx/clr/neg/not, xx=size, eeeeee=EA)
\r
121 int type=0,size=0,ea=0,use=0;
\r
125 size=(op>>6)&3; if (size>=3) return 1;
\r
129 case 1: case 2: case 3: break;
\r
130 default: return 1; // todo
\r
133 // See if we can do this opcode:
\r
134 if (EaCanRead (ea,size)==0) return 1;
\r
135 if (EaCanWrite(ea )==0) return 1;
\r
138 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
140 OpStart(op); Cycles=size<2?4:6;
\r
142 EaCalc (10,0x003f,ea,size);
\r
144 if (type!=1) EaRead (10,0,ea,size); // Don't need to read for 'clr'
\r
145 if (type==1) ot("\n");
\r
150 ot(" mov r1,#0\n");
\r
151 ot(" mov r9,#0x40000000 ;@ NZCV=0100\n");
\r
158 ot(" rsbs r1,r0,#0\n");
\r
166 ot(" mvn r1,r0\n");
\r
167 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
\r
172 EaWrite(10, 1,ea,size);
\r
179 // --------------------- Opcodes 0x4840+ ---------------------
\r
180 // Swap, 01001000 01000nnn swap Dn
\r
186 use=op&~0x0007; // Use same opcode for all An
\r
188 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
190 OpStart(op); Cycles=4;
\r
192 EaCalc (10,0x0007,ea,2);
\r
193 EaRead (10, 0,ea,2);
\r
195 ot(" mov r1,r0,ror #16\n");
\r
196 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");
\r
199 EaWrite(10, 1,8,2);
\r
206 // --------------------- Opcodes 0x4a00+ ---------------------
\r
207 // Emit a Tst opcode, 01001010 xxeeeeee
\r
214 size=(op>>6)&3; if (size>=3) return 1;
\r
216 // See if we can do this opcode:
\r
217 if (EaCanWrite(sea)==0) return 1;
\r
220 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
222 OpStart(op); Cycles=4;
\r
224 EaCalc ( 0,0x003f,sea,size);
\r
225 EaRead ( 0, 0,sea,size);
\r
227 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");
\r
228 ot(" mrs r9,cpsr ;@ r9=flags\n");
\r
235 // --------------------- Opcodes 0x4880+ ---------------------
\r
236 // Emit an Ext opcode, 01001000 1x000nnn
\r
245 shift=32-(8<<size);
\r
248 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
250 OpStart(op); Cycles=4;
\r
252 EaCalc (10,0x0007,ea,size+1);
\r
253 EaRead (10, 0,ea,size+1);
\r
255 ot(" mov r0,r0,asl #%d\n",shift);
\r
256 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");
\r
257 ot(" mrs r9,cpsr ;@ r9=flags\n");
\r
258 ot(" mov r1,r0,asr #%d\n",shift);
\r
261 EaWrite(10, 1,ea,size+1);
\r
267 // --------------------- Opcodes 0x50c0+ ---------------------
\r
268 // Emit a Set cc opcode, 0101cccc 11eeeeee
\r
275 "al","", "hi","ls","cc","cs","ne","eq",
\r
276 "vc","vs","pl","mi","ge","lt","gt","le"
\r
282 if ((ea&0x38)==0x08) return 1; // dbra, not scc
\r
284 // See if we can do this opcode:
\r
285 if (EaCanWrite(ea)==0) return 1;
\r
288 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
290 OpStart(op); Cycles=8;
\r
292 if (ea<0x10) Cycles=4;
\r
294 ot(" mov r1,#0\n");
\r
298 ot(";@ Is the condition true?\n");
\r
299 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");
\r
300 ot(" msr cpsr_flg,r9 ;@ ARM flags = 68000 flags\n");
\r
301 if ((cc&~1)==2) ot(" eor r9,r9,#0x20000000 ;@ Invert carry for hi/ls\n");
\r
302 ot(" mvn%s r1,r1\n",cond[cc]);
\r
305 if (ea<0x10) ot(" sub%s r5,r5,#2 ;@ Extra cycles\n",cond[cc]);
\r
308 EaCalc (0,0x003f, ea,size);
\r
309 EaWrite(0, 1, ea,size);
\r
315 // Emit a Asr/Lsr/Roxr/Ror opcode
\r
316 static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)
\r
319 int shift=32-(8<<size);
\r
321 if (count>=1) sprintf(pct,"#%d",count); // Fixed count
\r
325 ot(" mov r2,r8,lsr #9 ;@ Get 'n'\n");
\r
326 ot(" and r2,r2,#7\n\n"); strcpy(pct,"r2");
\r
331 ot(";@ Use Dn for count:\n");
\r
332 ot(" ldr r2,[r7,r2,lsl #2]\n");
\r
333 ot(" and r2,r2,#63\n");
\r
337 // Take 2*n cycles:
\r
338 if (count<0) ot(" sub r5,r5,r2,asl #1 ;@ Take 2*n cycles\n\n");
\r
339 else Cycles+=count<<1;
\r
344 if (dir==0 && size<2)
\r
346 ot(";@ For shift right, also copy to lowest bits (to get carry bit):\n");
\r
347 ot(" orr r0,r0,r0,lsr #%d\n",32-(8<<size));
\r
351 ot(";@ Shift register:\n");
\r
352 if (type==0) ot(" movs r0,r0,%s %s\n",dir?"asl":"asr",pct);
\r
353 if (type==1) ot(" movs r0,r0,%s %s\n",dir?"lsl":"lsr",pct);
\r
359 ot(";@ Check if result is zero:\n");
\r
360 ot(" movs r2,r0,lsr #%d\n",shift);
\r
361 ot(" orreq r9,r9,#0x40000000\n");
\r
366 // --------------------------------------
\r
372 if (shift) ot(" mov r0,r0,lsr #%d ;@ Shift down\n",shift);
\r
374 ot(";@ Rotate register through X:\n");
\r
375 if (strcmp("r2",pct)!=0) { ot(" mov r2,%s\n",pct); strcpy(pct,"r2"); } // Get into register
\r
379 ot(";@ Reduce r2 until <0:\n");
\r
380 ot("Reduce_%.4x%s\n",op,ms?"":":");
\r
381 ot(" subs r2,r2,#%d\n",wide+1);
\r
382 ot(" bpl Reduce_%.4x\n",op);
\r
383 ot(" add r2,r2,#%d ;@ Now r2=0-%d\n",wide+1,wide);
\r
387 if (dir) ot(" rsb r2,r2,#%d ;@ Reverse direction\n",wide+1);
\r
389 ot(";@ Rotate bits:\n");
\r
390 ot(" mov r3,r0,lsr r2 ;@ Get right part\n");
\r
391 ot(" rsb r2,r2,#%d\n",wide+1);
\r
392 ot(" movs r0,r0,lsl r2 ;@ Get left part\n");
\r
393 ot(" orr r0,r3,r0 ;@ r0=Rotated value\n");
\r
395 ot(";@ Insert X bit into r2-1:\n");
\r
396 ot(" ldrb r3,[r7,#0x45]\n");
\r
397 ot(" sub r2,r2,#1\n");
\r
398 ot(" and r3,r3,#2\n");
\r
399 ot(" mov r3,r3,lsr #1\n");
\r
400 ot(" orr r0,r0,r3,lsl r2\n");
\r
403 if (shift) ot(" movs r0,r0,lsl #%d ;@ Shift up and get correct NC flags\n",shift);
\r
408 // --------------------------------------
\r
414 ot(";@ Mirror value in whole 32 bits:\n");
\r
415 if (size<=0) ot(" orr r0,r0,r0,lsr #8\n");
\r
416 if (size<=1) ot(" orr r0,r0,r0,lsr #16\n");
\r
420 ot(";@ Rotate register:\n");
\r
423 if (dir) ot(" rsb r2,%s,#32\n",pct);
\r
424 ot(" movs r0,r0,ror %s\n",pct);
\r
429 if (dir) ror=32-ror;
\r
430 if (ror&31) ot(" movs r0,r0,ror #%d\n",ror);
\r
435 ot(";@ Get carry bit from bit 0:\n");
\r
436 ot(" mov r9,#0\n");
\r
437 ot(" ands r2,r0,#1\n");
\r
438 ot(" orrne r9,r9,#0x20000000\n");
\r
447 // --------------------------------------
\r
452 // Emit a Asr/Lsr/Roxr/Ror opcode - 1110cccd xxuttnnn
\r
453 // (ccc=count, d=direction xx=size extension, u=use reg for count, tt=type, nnn=register Dn)
\r
458 int size=0,usereg=0,type=0;
\r
464 if (size>=3) return 1; // todo Asr EA
\r
468 if (usereg==0) count=((count-1)&7)+1; // because ccc=000 means 8
\r
470 // Use the same opcode for target registers:
\r
473 // As long as count is not 8, use the same opcode for all shift counts::
\r
474 if (usereg==0 && count!=8) { use|=0x0e00; count=-1; }
\r
475 if (usereg) { use&=~0x0e00; count=-1; } // Use same opcode for all Dn
\r
477 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
479 OpStart(op); Cycles=size<2?6:8;
\r
481 EaCalc(10,0x0007, ea,size);
\r
482 EaRead(10, 0, ea,size,1);
\r
484 EmitAsr(op,type,dir,count, size,usereg);
\r
486 EaWrite(10, 0, ea,size,1);
\r
493 // Asr/l/Ror/l etc EA - 11100ttd 11eeeeee
\r
494 int OpAsrEa(int op)
\r
496 int use=0,type=0,dir=0,ea=0,size=1;
\r
502 if (ea<0x10) return 1;
\r
503 // See if we can do this opcode:
\r
504 if (EaCanRead(ea,0)==0) return 1;
\r
505 if (EaCanWrite(ea)==0) return 1;
\r
508 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler
\r
510 OpStart(op); Cycles=8;
\r
512 EaCalc (10,0x003f,ea,size);
\r
513 EaRead (10, 0,ea,size,1);
\r
515 EmitAsr(op,type,dir,1, size,0);
\r
517 ot(";@ Save shifted value back to EA:\n");
\r
518 ot(" mov r1,r0\n");
\r
519 EaWrite(10, 1,ea,size,1);
\r