first check-in of Cyclone 0.069 under GPLv2 and MAME License. Pico Disa.c/h included too
[cyclone68000.git] / Cyclone / OpLogic.cpp
CommitLineData
6003a768 1#include "app.h"\r
2\r
3// --------------------- Opcodes 0x0100+ ---------------------\r
4// Emit a Btst (Register) opcode 0000nnn1 00aaaaaa\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;\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
30 OpStart(op); Cycles=4;\r
31 if (tea<0x10) Cycles+=2;\r
32 if (type>0) Cycles+=4;\r
33\r
34 ot(" mov r10,#1\n");\r
35\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
40 ot("\n");\r
41\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
46 ot("\n");\r
47\r
48 if (type>0)\r
49 {\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
53 ot("\n");\r
54 EaWrite(11, 1,tea,size);\r
55 }\r
56 OpEnd();\r
57\r
58 return 0;\r
59}\r
60\r
61// --------------------- Opcodes 0x0800+ ---------------------\r
62// Emit a Btst/Bchg/Bclr/Bset (Immediate) opcode 00001000 ttaaaaaa nn\r
63int OpBtstImm(int op)\r
64{\r
65 int type=0,sea=0,tea=0;\r
66 int use=0;\r
67 int size=0;\r
68\r
69 type=(op>>6)&3;\r
70 // Get source and target EA\r
71 sea= 0x003c;\r
72 tea=op&0x003f;\r
73 if (tea<0x10) size=2; // For registers, 32-bits\r
74\r
75 // See if we can do this opcode:\r
76 if (EaCanRead(tea,0)==0) return 1;\r
77 if (type>0)\r
78 {\r
79 if (EaCanWrite(tea)==0) return 1;\r
80 }\r
81\r
82 use=OpBase(op);\r
83 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
84\r
85 OpStart(op); Cycles=4;\r
86 if (type<3 && tea<0x10) Cycles+=2;\r
87 if (type>0) Cycles+=4;\r
88\r
89 ot(" mov r10,#1\n");\r
90 ot("\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
95 ot("\n");\r
96\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
101 ot("\n");\r
102\r
103 if (type>0)\r
104 {\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
108 ot("\n");\r
109 EaWrite(11, 1,tea,size);\r
110 }\r
111\r
112 OpEnd();\r
113\r
114 return 0;\r
115}\r
116\r
117// --------------------- Opcodes 0x4000+ ---------------------\r
118int OpNeg(int op)\r
119{\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
122\r
123 type=(op>>9)&3;\r
124 ea =op&0x003f;\r
125 size=(op>>6)&3; if (size>=3) return 1;\r
126\r
127 switch (type)\r
128 {\r
129 case 1: case 2: case 3: break;\r
130 default: return 1; // todo\r
131 }\r
132\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
136\r
137 use=OpBase(op);\r
138 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
139\r
140 OpStart(op); Cycles=size<2?4:6;\r
141\r
142 EaCalc (10,0x003f,ea,size);\r
143\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
146\r
147 if (type==1)\r
148 {\r
149 ot(";@ Clear:\n");\r
150 ot(" mov r1,#0\n");\r
151 ot(" mov r9,#0x40000000 ;@ NZCV=0100\n");\r
152 ot("\n");\r
153 }\r
154\r
155 if (type==2)\r
156 {\r
157 ot(";@ Neg:\n");\r
158 ot(" rsbs r1,r0,#0\n");\r
159 OpGetFlags(1,1);\r
160 ot("\n");\r
161 }\r
162\r
163 if (type==3)\r
164 {\r
165 ot(";@ Not:\n");\r
166 ot(" mvn r1,r0\n");\r
167 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
168 OpGetFlags(0,0);\r
169 ot("\n");\r
170 }\r
171\r
172 EaWrite(10, 1,ea,size);\r
173\r
174 OpEnd();\r
175\r
176 return 0;\r
177}\r
178\r
179// --------------------- Opcodes 0x4840+ ---------------------\r
180// Swap, 01001000 01000nnn swap Dn\r
181int OpSwap(int op)\r
182{\r
183 int ea=0,use=0;\r
184\r
185 ea=op&7;\r
186 use=op&~0x0007; // Use same opcode for all An\r
187\r
188 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
189\r
190 OpStart(op); Cycles=4;\r
191\r
192 EaCalc (10,0x0007,ea,2);\r
193 EaRead (10, 0,ea,2);\r
194\r
195 ot(" mov r1,r0,ror #16\n");\r
196 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
197 OpGetFlags(0,0);\r
198\r
199 EaWrite(10, 1,8,2);\r
200\r
201 OpEnd();\r
202\r
203 return 0;\r
204}\r
205\r
206// --------------------- Opcodes 0x4a00+ ---------------------\r
207// Emit a Tst opcode, 01001010 xxeeeeee\r
208int OpTst(int op)\r
209{\r
210 int sea=0;\r
211 int size=0,use=0;\r
212\r
213 sea=op&0x003f;\r
214 size=(op>>6)&3; if (size>=3) return 1;\r
215\r
216 // See if we can do this opcode:\r
217 if (EaCanWrite(sea)==0) return 1;\r
218\r
219 use=OpBase(op);\r
220 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
221\r
222 OpStart(op); Cycles=4;\r
223\r
224 EaCalc ( 0,0x003f,sea,size);\r
225 EaRead ( 0, 0,sea,size);\r
226\r
227 ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n");\r
228 ot(" mrs r9,cpsr ;@ r9=flags\n");\r
229 ot("\n");\r
230\r
231 OpEnd();\r
232 return 0;\r
233}\r
234\r
235// --------------------- Opcodes 0x4880+ ---------------------\r
236// Emit an Ext opcode, 01001000 1x000nnn\r
237int OpExt(int op)\r
238{\r
239 int ea=0;\r
240 int size=0,use=0;\r
241 int shift=0;\r
242\r
243 ea=op&0x0007;\r
244 size=(op>>6)&1;\r
245 shift=32-(8<<size);\r
246\r
247 use=OpBase(op);\r
248 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
249\r
250 OpStart(op); Cycles=4;\r
251\r
252 EaCalc (10,0x0007,ea,size+1);\r
253 EaRead (10, 0,ea,size+1);\r
254\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
259 ot("\n");\r
260\r
261 EaWrite(10, 1,ea,size+1);\r
262\r
263 OpEnd();\r
264 return 0;\r
265}\r
266\r
267// --------------------- Opcodes 0x50c0+ ---------------------\r
268// Emit a Set cc opcode, 0101cccc 11eeeeee\r
269int OpSet(int op)\r
270{\r
271 int cc=0,ea=0;\r
272 int size=0,use=0;\r
273 char *cond[16]=\r
274 {\r
275 "al","", "hi","ls","cc","cs","ne","eq",\r
276 "vc","vs","pl","mi","ge","lt","gt","le"\r
277 };\r
278\r
279 cc=(op>>8)&15;\r
280 ea=op&0x003f;\r
281\r
282 if ((ea&0x38)==0x08) return 1; // dbra, not scc\r
283 \r
284 // See if we can do this opcode:\r
285 if (EaCanWrite(ea)==0) return 1;\r
286\r
287 use=OpBase(op);\r
288 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
289\r
290 OpStart(op); Cycles=8;\r
291\r
292 if (ea<0x10) Cycles=4;\r
293\r
294 ot(" mov r1,#0\n");\r
295\r
296 if (cc!=1)\r
297 {\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
303 }\r
304\r
305 if (ea<0x10) ot(" sub%s r5,r5,#2 ;@ Extra cycles\n",cond[cc]);\r
306 ot("\n");\r
307\r
308 EaCalc (0,0x003f, ea,size);\r
309 EaWrite(0, 1, ea,size);\r
310\r
311 OpEnd();\r
312 return 0;\r
313}\r
314\r
315// Emit a Asr/Lsr/Roxr/Ror opcode\r
316static int EmitAsr(int op,int type,int dir,int count,int size,int usereg)\r
317{\r
318 char pct[8]="";\r
319 int shift=32-(8<<size);\r
320\r
321 if (count>=1) sprintf(pct,"#%d",count); // Fixed count\r
322\r
323 if (count<0)\r
324 {\r
325 ot(" mov r2,r8,lsr #9 ;@ Get 'n'\n");\r
326 ot(" and r2,r2,#7\n\n"); strcpy(pct,"r2");\r
327 }\r
328\r
329 if (usereg)\r
330 {\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
334 ot("\n");\r
335 }\r
336\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
340\r
341 if (type<2)\r
342 {\r
343 // Asr/Lsr\r
344 if (dir==0 && size<2)\r
345 {\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
348 ot("\n");\r
349 }\r
350\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
354 OpGetFlags(0,1);\r
355 ot("\n");\r
356\r
357 if (size<2)\r
358 {\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
362 ot("\n");\r
363 }\r
364 }\r
365\r
366 // --------------------------------------\r
367 if (type==2)\r
368 {\r
369 // Roxr\r
370 int wide=8<<size;\r
371\r
372 if (shift) ot(" mov r0,r0,lsr #%d ;@ Shift down\n",shift);\r
373\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
376\r
377 if (count!=8)\r
378 {\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
384 ot("\n");\r
385 }\r
386\r
387 if (dir) ot(" rsb r2,r2,#%d ;@ Reverse direction\n",wide+1);\r
388\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
394\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
401 ot("\n");\r
402\r
403 if (shift) ot(" movs r0,r0,lsl #%d ;@ Shift up and get correct NC flags\n",shift);\r
404 OpGetFlags(0,1);\r
405 ot("\n");\r
406 }\r
407\r
408 // --------------------------------------\r
409 if (type==3)\r
410 {\r
411 // Ror\r
412 if (size<2)\r
413 {\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
417 ot("\n");\r
418 }\r
419\r
420 ot(";@ Rotate register:\n");\r
421 if (count<0)\r
422 {\r
423 if (dir) ot(" rsb r2,%s,#32\n",pct);\r
424 ot(" movs r0,r0,ror %s\n",pct);\r
425 }\r
426 else\r
427 {\r
428 int ror=count;\r
429 if (dir) ror=32-ror;\r
430 if (ror&31) ot(" movs r0,r0,ror #%d\n",ror);\r
431 }\r
432\r
433 if (dir)\r
434 {\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
439 }\r
440 else\r
441 {\r
442 OpGetFlags(0,0);\r
443 }\r
444 ot("\n");\r
445\r
446 }\r
447 // --------------------------------------\r
448 \r
449 return 0;\r
450}\r
451\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
454int OpAsr(int op)\r
455{\r
456 int ea=0,use=0;\r
457 int count=0,dir=0;\r
458 int size=0,usereg=0,type=0;\r
459\r
460 ea=0;\r
461 count =(op>>9)&7;\r
462 dir =(op>>8)&1;\r
463 size =(op>>6)&3;\r
464 if (size>=3) return 1; // todo Asr EA\r
465 usereg=(op>>5)&1;\r
466 type =(op>>3)&3;\r
467\r
468 if (usereg==0) count=((count-1)&7)+1; // because ccc=000 means 8\r
469\r
470 // Use the same opcode for target registers:\r
471 use=op&~0x0007;\r
472\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
476\r
477 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
478\r
479 OpStart(op); Cycles=size<2?6:8;\r
480\r
481 EaCalc(10,0x0007, ea,size);\r
482 EaRead(10, 0, ea,size,1);\r
483\r
484 EmitAsr(op,type,dir,count, size,usereg);\r
485\r
486 EaWrite(10, 0, ea,size,1);\r
487\r
488 OpEnd();\r
489\r
490 return 0;\r
491}\r
492\r
493// Asr/l/Ror/l etc EA - 11100ttd 11eeeeee \r
494int OpAsrEa(int op)\r
495{\r
496 int use=0,type=0,dir=0,ea=0,size=1;\r
497\r
498 type=(op>>9)&3;\r
499 dir =(op>>8)&1;\r
500 ea = op&0x3f;\r
501\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
506\r
507 use=OpBase(op);\r
508 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
509\r
510 OpStart(op); Cycles=8;\r
511\r
512 EaCalc (10,0x003f,ea,size);\r
513 EaRead (10, 0,ea,size,1);\r
514\r
515 EmitAsr(op,type,dir,1, size,0);\r
516\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
520\r
521 OpEnd();\r
522 return 0;\r
523}\r