more MAME fixes, some optimization
[picodrive.git] / cpu / Cyclone / OpArith.cpp
CommitLineData
cc68a136 1\r
2#include "app.h"\r
3\r
4// --------------------- Opcodes 0x0000+ ---------------------\r
5// Emit an Ori/And/Sub/Add/Eor/Cmp Immediate opcode, 0000ttt0 ssaaaaaa\r
6int OpArith(int op)\r
7{\r
8 int type=0,size=0;\r
9 int sea=0,tea=0;\r
10 int use=0;\r
11\r
12 // Get source and target EA\r
13 type=(op>>9)&7; if (type==4 || type>=7) return 1;\r
14 size=(op>>6)&3; if (size>=3) return 1;\r
15 sea= 0x003c;\r
16 tea=op&0x003f;\r
17\r
18 // See if we can do this opcode:\r
19 if (EaCanRead(tea,size)==0) return 1;\r
20 if (EaCanWrite(tea)==0 || EaAn(tea)) return 1;\r
21\r
22 use=OpBase(op);\r
23 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
24\r
cfb3dfa0 25 OpStart(op, sea, tea); Cycles=4;\r
cc68a136 26\r
27 EaCalc(10,0x0000, sea,size,1);\r
cc68a136 28 EaCalc(11,0x003f, tea,size,1);\r
cfb3dfa0 29 EaRead(10, 10, sea,size,0,1);\r
cc68a136 30 EaRead(11, 0, tea,size,0x003f,1);\r
31\r
32 ot(";@ Do arithmetic:\n");\r
33\r
34 if (type==0) ot(" orr r1,r0,r10\n");\r
35 if (type==1) ot(" and r1,r0,r10\n");\r
36 if (type==2) ot(" subs r1,r0,r10 ;@ Defines NZCV\n");\r
37 if (type==3) ot(" adds r1,r0,r10 ;@ Defines NZCV\n");\r
38 if (type==5) ot(" eor r1,r0,r10\n");\r
39 if (type==6) ot(" cmp r0,r10 ;@ Defines NZCV\n");\r
40\r
41 if (type<2 || type==5) ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); // 0,1,5\r
42\r
43 if (type< 2) OpGetFlags(0,0); // Ori/And\r
44 if (type==2) OpGetFlags(1,1); // Sub: Subtract/X-bit\r
45 if (type==3) OpGetFlags(0,1); // Add: X-bit\r
46 if (type==5) OpGetFlags(0,0); // Eor\r
47 if (type==6) OpGetFlags(1,0); // Cmp: Subtract\r
48 ot("\n");\r
49\r
50 if (type!=6)\r
51 {\r
52 EaWrite(11, 1, tea,size,0x003f,1);\r
53 }\r
54\r
55 // Correct cycles:\r
56 if (type==6)\r
57 {\r
58 if (size>=2 && tea<0x10) Cycles+=2;\r
59 }\r
60 else\r
61 {\r
62 if (size>=2) Cycles+=4;\r
63 if (tea>=8) Cycles+=4;\r
64 if (type==1 && size>=2 && tea<8) Cycles-=2;\r
65 }\r
66\r
cfb3dfa0 67 OpEnd(sea,tea);\r
cc68a136 68\r
69 return 0;\r
70}\r
71\r
72// --------------------- Opcodes 0x5000+ ---------------------\r
73int OpAddq(int op)\r
74{\r
75 // 0101nnnt xxeeeeee (nnn=#8,1-7 t=addq/subq xx=size, eeeeee=EA)\r
76 int num=0,type=0,size=0,ea=0;\r
77 int use=0;\r
78 char count[16]="";\r
79 int shift=0;\r
80\r
81 num =(op>>9)&7; if (num==0) num=8;\r
82 type=(op>>8)&1;\r
83 size=(op>>6)&3; if (size>=3) return 1;\r
84 ea = op&0x3f;\r
85\r
86 // See if we can do this opcode:\r
87 if (EaCanRead (ea,size)==0) return 1;\r
88 if (EaCanWrite(ea) ==0) return 1;\r
89 if (size == 0 && EaAn(ea) ) return 1;\r
90\r
91 use=OpBase(op,1);\r
92\r
93 if (num!=8) use|=0x0e00; // If num is not 8, use same handler\r
94 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
95\r
a6785576 96 OpStart(op,ea);\r
cc68a136 97 Cycles=ea<8?4:8;\r
98 if(type==0&&size==1) Cycles=ea<0x10?4:8;\r
99 if(size>=2) Cycles=ea<0x10?8:12;\r
100\r
101 if (size>0 && (ea&0x38)==0x08) size=2; // addq.w #n,An is also 32-bit\r
102\r
103 EaCalc(10,0x003f, ea,size,1);\r
104 EaRead(10, 0, ea,size,0x003f,1);\r
105\r
106 shift=32-(8<<size);\r
107\r
108 if (num!=8)\r
109 {\r
110 int lsr=9-shift;\r
111\r
112 if (lsr>=0) ot(" mov r2,r8,lsr #%d ;@ Get quick value\n", lsr);\r
113 else ot(" mov r2,r8,lsl #%d ;@ Get quick value\n",-lsr);\r
114\r
115 ot(" and r2,r2,#0x%.4x\n",7<<shift);\r
116 ot("\n");\r
117 strcpy(count,"r2");\r
118 }\r
119\r
120 if (num==8) sprintf(count,"#0x%.4x",8<<shift);\r
121\r
122 if (type==0) ot(" adds r1,r0,%s\n",count);\r
123 if (type==1) ot(" subs r1,r0,%s\n",count);\r
124\r
125 if ((ea&0x38)!=0x08) OpGetFlags(type,1);\r
126 ot("\n");\r
127\r
128 EaWrite(10, 1, ea,size,0x003f,1);\r
129\r
cfb3dfa0 130 OpEnd(ea);\r
cc68a136 131\r
132 return 0;\r
133}\r
134\r
135// --------------------- Opcodes 0x8000+ ---------------------\r
136// 1t0tnnnd xxeeeeee (tt=type:or/sub/and/add xx=size, eeeeee=EA)\r
137int OpArithReg(int op)\r
138{\r
139 int use=0;\r
140 int type=0,size=0,dir=0,rea=0,ea=0;\r
141\r
142 type=(op>>12)&5;\r
143 rea =(op>> 9)&7;\r
144 dir =(op>> 8)&1; // er,re\r
145 size=(op>> 6)&3; if (size>=3) return 1;\r
146 ea = op&0x3f;\r
147\r
148 if (dir && ea<0x10) return 1; // addx/subx opcode\r
149\r
150 // See if we can do this opcode:\r
151 if (dir==0 && EaCanRead (ea,size)==0) return 1;\r
152 if (dir && EaCanWrite(ea)==0) return 1;\r
153 if ((size==0||!(type&1))&&EaAn(ea)) return 1;\r
154\r
155 use=OpBase(op);\r
156 use&=~0x0e00; // Use same opcode for Dn\r
157 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
158\r
a6785576 159 OpStart(op,ea); Cycles=4;\r
cc68a136 160\r
161 ot(";@ Get r10=EA r11=EA value\n");\r
162 EaCalc(10,0x003f, ea,size,1);\r
163 EaRead(10, 11, ea,size,0x003f,1);\r
164 ot(";@ Get r0=Register r1=Register value\n");\r
165 EaCalc( 0,0x0e00,rea,size,1);\r
166 EaRead( 0, 1,rea,size,0x0e00,1);\r
167\r
168 ot(";@ Do arithmetic:\n");\r
169 if (type==0) ot(" orr ");\r
170 if (type==1) ot(" subs ");\r
171 if (type==4) ot(" and ");\r
172 if (type==5) ot(" adds ");\r
173 if (dir) ot("r1,r11,r1\n");\r
174 else ot("r1,r1,r11\n");\r
175\r
176 if ((type&1)==0) ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
177\r
178 OpGetFlags(type==1,type&1); // 1==subtract\r
179 ot("\n");\r
180\r
181 ot(";@ Save result:\n");\r
182 if (dir) EaWrite(10, 1, ea,size,0x003f,1);\r
183 else EaWrite( 0, 1,rea,size,0x0e00,1);\r
184\r
185 if(rea==ea) {\r
186 if(ea<8) Cycles=(size>=2)?8:4; else Cycles+=(size>=2)?26:14;\r
187 } else if(dir) {\r
188 Cycles+=4;\r
189 if(size>=2) Cycles+=4;\r
190 } else {\r
191 if(size>=2) {\r
a6785576 192 Cycles+=2;\r
193 if(ea<0x10||ea==0x3c) Cycles+=2;\r
194 }\r
cc68a136 195 }\r
196\r
cfb3dfa0 197 OpEnd(ea);\r
cc68a136 198\r
199 return 0;\r
200}\r
201\r
202// --------------------- Opcodes 0x80c0+ ---------------------\r
203int OpMul(int op)\r
204{\r
205 // Div/Mul: 1m00nnns 11eeeeee (m=Mul, nnn=Register Dn, s=signed, eeeeee=EA)\r
206 int type=0,rea=0,sign=0,ea=0;\r
207 int use=0;\r
208\r
209 type=(op>>14)&1; // div/mul\r
210 rea =(op>> 9)&7;\r
211 sign=(op>> 8)&1;\r
212 ea = op&0x3f;\r
213\r
214 // See if we can do this opcode:\r
215 if (EaCanRead(ea,1)==0||EaAn(ea)) return 1;\r
216\r
217 use=OpBase(op);\r
218 use&=~0x0e00; // Use same for all registers\r
219 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
220\r
a6785576 221 OpStart(op,ea);\r
cc68a136 222 if(type) Cycles=54;\r
223 else Cycles=sign?158:140;\r
224\r
225 EaCalc(10,0x003f, ea, 1);\r
226 EaRead(10, 10, ea, 1,0x003f);\r
227\r
228 EaCalc (0,0x0e00,rea, 2,1);\r
229 EaRead (0, 2,rea, 2,0x0e00,1);\r
230\r
231 if (type==0) // div\r
232 {\r
233 // the manual says C is always cleared, but neither Musashi nor FAME do that\r
234 //ot(" bic r9,r9,#0x20000000 ;@ always clear C\n");\r
235 ot(" tst r10,r10\n");\r
236 ot(" beq divzero%.4x ;@ division by zero\n",op);\r
237 ot("\n");\r
238 \r
239 if (sign)\r
240 {\r
241 ot(" mov r11,#0 ;@ r11 = 1 or 2 if the result is negative\n");\r
242 ot(" orrmi r11,r11,#1\n");\r
243 ot(" rsbmi r10,r10,#0 ;@ Make r10 positive\n");\r
244 ot("\n");\r
245 ot(" tst r2,r2\n");\r
246 ot(" orrmi r11,r11,#2\n");\r
247 ot(" rsbmi r2,r2,#0 ;@ Make r2 positive\n");\r
248 ot("\n");\r
249 }\r
250 else\r
a6785576 251 {\r
cc68a136 252 ot(" mov r10,r10,lsl #16 ;@ use only 16 bits of divisor\n");\r
253 ot(" mov r10,r10,lsr #16\n");\r
a6785576 254 }\r
cc68a136 255\r
256 ot(";@ Divide r2 by r10\n");\r
257 ot(" mov r3,#0\n");\r
258 ot(" mov r1,r10\n");\r
259 ot("\n");\r
260 ot(";@ Shift up divisor till it's just less than numerator\n");\r
261 ot("Shift%.4x%s\n",op,ms?"":":");\r
262 ot(" cmp r1,r2,lsr #1\n");\r
263 ot(" movls r1,r1,lsl #1\n");\r
264 ot(" bcc Shift%.4x\n",op);\r
265 ot("\n");\r
266\r
267 ot("Divide%.4x%s\n",op,ms?"":":");\r
268 ot(" cmp r2,r1\n");\r
269 ot(" adc r3,r3,r3 ;@ Double r3 and add 1 if carry set\n");\r
270 ot(" subcs r2,r2,r1\n");\r
271 ot(" teq r1,r10\n");\r
272 ot(" movne r1,r1,lsr #1\n");\r
273 ot(" bne Divide%.4x\n",op);\r
274 ot("\n");\r
275 ot(";@r3==quotient,r2==remainder\n");\r
276\r
277 if (sign)\r
278 {\r
a6785576 279 // sign correction\r
cc68a136 280 ot(" and r1,r11,#1\n");\r
281 ot(" teq r1,r11,lsr #1\n");\r
282 ot(" rsbne r3,r3,#0 ;@ negate if quotient is negative\n");\r
283 ot(" tst r11,#2\n");\r
284 ot(" rsbne r2,r2,#0 ;@ negate the remainder if divident was negative\n");\r
285 ot("\n");\r
286\r
a6785576 287 // signed overflow check\r
288 ot(" mov r1,r3,asl #16\n");\r
289 ot(" cmp r3,r1,asr #16 ;@ signed overflow?\n");\r
cc68a136 290 ot(" orrne r9,r9,#0x10000000 ;@ set overflow flag\n");\r
291 ot(" bne endofop%.4x ;@ overflow!\n",op);\r
292 }\r
a6785576 293 else\r
294 {\r
295 // overflow check\r
296 ot(" movs r1,r3,lsr #16 ;@ check for overflow condition\n");\r
cc68a136 297 ot(" orrne r9,r9,#0x10000000 ;@ set overflow flag\n");\r
298 ot(" bne endofop%.4x ;@ overflow!\n",op);\r
a6785576 299 }\r
cc68a136 300\r
301 ot(" mov r1,r3,lsl #16 ;@ Clip to 16-bits\n");\r
302 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
303 OpGetFlags(0,0);\r
304\r
305 ot(" mov r1,r1,lsr #16\n");\r
306 ot(" orr r1,r1,r2,lsl #16 ;@ Insert remainder\n");\r
307 }\r
308\r
309 if (type==1)\r
310 {\r
311 char *shift="asr";\r
312\r
313 ot(";@ Get 16-bit signs right:\n");\r
314 if (sign==0) { ot(" mov r10,r10,lsl #16\n"); shift="lsr"; }\r
315 ot(" mov r2,r2,lsl #16\n");\r
316\r
317 if (sign==0) ot(" mov r10,r10,lsr #16\n");\r
318 ot(" mov r2,r2,%s #16\n",shift);\r
319 ot("\n");\r
320\r
321 ot(" mul r1,r2,r10\n");\r
322 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
323 OpGetFlags(0,0);\r
324 }\r
325 ot("\n");\r
326\r
327 EaWrite(0, 1,rea, 2,0x0e00,1);\r
328\r
329 ot("endofop%.4x%s\n",op,ms?"":":");\r
cfb3dfa0 330 OpEnd(ea);\r
cc68a136 331\r
332 ot("divzero%.4x%s\n",op,ms?"":":");\r
333 ot(" mov r0,#0x14 ;@ Divide by zero\n");\r
334 ot(" bl Exception\n");\r
335 Cycles+=38;\r
cfb3dfa0 336 OpEnd(ea);\r
cc68a136 337 ot("\n");\r
338\r
339 return 0;\r
340}\r
341\r
342// Get X Bit into carry - trashes r2\r
343int GetXBit(int subtract)\r
344{\r
345 ot(";@ Get X bit:\n");\r
346 ot(" ldrb r2,[r7,#0x45]\n");\r
347 if (subtract) ot(" mvn r2,r2,lsl #28 ;@ Invert it\n");\r
348 else ot(" mov r2,r2,lsl #28\n");\r
349 ot(" msr cpsr_flg,r2 ;@ Get into Carry\n");\r
350 ot("\n");\r
351 return 0;\r
352}\r
353\r
354// --------------------- Opcodes 0x8100+ ---------------------\r
355// 1t00ddd1 0000asss - sbcd/abcd Ds,Dd or -(As),-(Ad)\r
356int OpAbcd(int op)\r
357{\r
358 int use=0;\r
359 int type=0,sea=0,addr=0,dea=0;\r
360 \r
361 type=(op>>14)&1; // sbcd/abcd\r
362 dea =(op>> 9)&7;\r
363 addr=(op>> 3)&1;\r
364 sea = op &7;\r
365\r
366 if (addr) { sea|=0x20; dea|=0x20; }\r
367\r
368 use=op&~0x0e07; // Use same opcode for all registers..\r
369 if (sea==0x27||dea==0x27) use=op; // ..except -(a7)\r
370 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
371\r
cfb3dfa0 372 OpStart(op,sea,dea); Cycles=6;\r
cc68a136 373\r
374 EaCalc( 0,0x0007, sea,0,1);\r
375 EaRead( 0, 10, sea,0,0x0007,1);\r
376 EaCalc(11,0x0e00, dea,0,1);\r
377 EaRead(11, 1, dea,0,0x0e00,1);\r
378\r
379 ot(" bic r9,r9,#0xb1000000 ;@ clear all flags except old Z\n");\r
380\r
381 if (type)\r
382 {\r
383 ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");\r
384 ot(" mov r3,#0x00f00000\n");\r
385 ot(" and r2,r3,r1,lsr #4\n");\r
a6785576 386 ot(" tst r0,#2\n");\r
cc68a136 387 ot(" and r0,r3,r10,lsr #4\n");\r
388 ot(" add r0,r0,r2\n");\r
389 ot(" addne r0,r0,#0x00100000\n");\r
390// ot(" tst r0,#0x00800000\n");\r
391// ot(" orreq r9,r9,#0x01000000 ;@ Undefined V behavior\n");\r
392 ot(" cmp r0,#0x00900000\n");\r
393 ot(" addhi r0,r0,#0x00600000 ;@ Decimal adjust units\n");\r
394\r
395 ot(" mov r2,r1,lsr #28\n");\r
396 ot(" add r0,r0,r2,lsl #24\n");\r
397 ot(" mov r2,r10,lsr #28\n");\r
398 ot(" add r0,r0,r2,lsl #24\n");\r
399 ot(" cmp r0,#0x09900000\n");\r
a6785576 400 ot(" orrhi r9,r9,#0x20000000 ;@ C\n");\r
401 ot(" subhi r0,r0,#0x0a000000\n");\r
402// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");\r
403// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");\r
cc68a136 404 ot(" movs r0,r0,lsl #4\n");\r
a6785576 405 ot(" orrmi r9,r9,#0x90000000 ;@ Undefined N+V behavior\n"); // this is what Musashi really does\r
406 ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");\r
cc68a136 407 }\r
408 else\r
409 {\r
410 ot(" ldrb r0,[r7,#0x45] ;@ Get X bit\n");\r
411 ot(" mov r3,#0x00f00000\n");\r
412 ot(" and r2,r3,r10,lsr #4\n");\r
a6785576 413 ot(" tst r0,#2\n");\r
cc68a136 414 ot(" and r0,r3,r1,lsr #4\n");\r
415 ot(" sub r0,r0,r2\n");\r
416 ot(" subne r0,r0,#0x00100000\n");\r
417// ot(" tst r0,#0x00800000\n");\r
418// ot(" orreq r9,r9,#0x01000000 ;@ Undefined V behavior\n");\r
419 ot(" cmp r0,#0x00900000\n");\r
420 ot(" subhi r0,r0,#0x00600000 ;@ Decimal adjust units\n");\r
421\r
422 ot(" mov r2,r1,lsr #28\n");\r
423 ot(" add r0,r0,r2,lsl #24\n");\r
424 ot(" mov r2,r10,lsr #28\n");\r
425 ot(" sub r0,r0,r2,lsl #24\n");\r
426 ot(" cmp r0,#0x09900000\n");\r
a6785576 427 ot(" orrhi r9,r9,#0xa0000000 ;@ N and C\n");\r
428 ot(" addhi r0,r0,#0x0a000000\n");\r
429// ot(" and r3,r9,r0,lsr #3 ;@ Undefined V behavior part II\n");\r
430// ot(" orr r9,r9,r3,lsl #4 ;@ V\n");\r
cc68a136 431 ot(" movs r0,r0,lsl #4\n");\r
a6785576 432// ot(" orrmi r9,r9,#0x80000000 ;@ Undefined N behavior\n");\r
433 ot(" bicne r9,r9,#0x40000000 ;@ Z flag\n");\r
cc68a136 434 }\r
435\r
436 ot(" mov r2,r9,lsr #28\n");\r
437 ot(" strb r2,[r7,#0x45] ;@ Save X bit\n");\r
438\r
439 EaWrite(11, 0, dea,0,0x0e00,1);\r
cfb3dfa0 440 OpEnd(sea,dea);\r
cc68a136 441\r
442 return 0;\r
443}\r
444\r
445// 01008000 00eeeeee - nbcd <ea>\r
446int OpNbcd(int op)\r
447{\r
448 int use=0;\r
449 int ea=0;\r
450 \r
451 ea=op&0x3f;\r
452\r
453 if(EaCanWrite(ea)==0||EaAn(ea)) return 1;\r
454\r
455 use=OpBase(op);\r
456 if(op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
457\r
a6785576 458 OpStart(op,ea); Cycles=6;\r
cc68a136 459 if(ea >= 8) Cycles+=2;\r
460\r
461 EaCalc(10,0x3f, ea,0,1);\r
462 EaRead(10, 0, ea,0,0x3f,1);\r
463\r
464 // this is rewrite of Musashi's code\r
465 ot(" ldrb r2,[r7,#0x45]\n");\r
466 ot(" tst r2,#2\n");\r
467 ot(" mov r2,r0\n");\r
468 ot(" addne r2,r0,#0x01000000 ;@ add X\n");\r
469 ot(" rsbs r1,r2,#0x9a000000 ;@ do arithmetic\n");\r
470\r
471 ot(" bic r9,r9,#0xb0000000 ;@ clear all flags, except Z\n");\r
472 ot(" orrmi r9,r9,#0x80000000 ;@ N\n");\r
473 ot(" cmp r1,#0x9a000000\n");\r
474 ot(" beq finish%.4x\n",op);\r
475 ot("\n");\r
476\r
477 ot(" mvn r3,r9,lsr #3 ;@ Undefined V behavior\n",op);\r
478 ot(" and r2,r1,#0x0f000000\n");\r
479 ot(" cmp r2,#0x0a000000\n");\r
480 ot(" andeq r1,r1,#0xf0000000\n");\r
481 ot(" addeq r1,r1,#0x10000000\n");\r
482 ot(" and r3,r3,r1,lsr #3 ;@ Undefined V behavior part II\n",op);\r
483 ot(" tst r1,r1\n");\r
484 ot(" orr r9,r9,r3 ;@ save V\n",op);\r
485 ot(" bicne r9,r9,#0x40000000 ;@ Z\n");\r
486 ot(" orr r9,r9,#0x20000000 ;@ C\n");\r
487 ot("\n");\r
488\r
489 EaWrite(10, 1, ea,0,0x3f,1);\r
490\r
491 ot("finish%.4x%s\n",op,ms?"":":");\r
492 ot(" mov r2,r9,lsr #28\n");\r
493 ot(" strb r2, [r7,#0x45]\n");\r
494\r
cfb3dfa0 495 OpEnd(ea);\r
cc68a136 496\r
497 return 0;\r
498}\r
499\r
500// --------------------- Opcodes 0x90c0+ ---------------------\r
501// Suba/Cmpa/Adda 1tt1nnnx 11eeeeee (tt=type, x=size, eeeeee=Source EA)\r
502int OpAritha(int op)\r
503{\r
504 int use=0;\r
505 int type=0,size=0,sea=0,dea=0;\r
506\r
507 // Suba/Cmpa/Adda/(invalid):\r
508 type=(op>>13)&3; if (type>=3) return 1;\r
509\r
510 size=(op>>8)&1; size++;\r
511 dea=(op>>9)&7; dea|=8; // Dest=An\r
512 sea=op&0x003f; // Source\r
513\r
514 // See if we can do this opcode:\r
515 if (EaCanRead(sea,size)==0) return 1;\r
516\r
517 use=OpBase(op);\r
518 use&=~0x0e00; // Use same opcode for An\r
519 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
520\r
a6785576 521 OpStart(op,sea); Cycles=(size==2)?6:8;\r
cc68a136 522 if(size==2&&(sea<0x10||sea==0x3c)) Cycles+=2;\r
523 if(type==1) Cycles=6;\r
524\r
525 \r
526 EaCalc ( 0,0x003f, sea,size);\r
527 EaRead ( 0, 10, sea,size,0x003f);\r
528\r
529 EaCalc ( 0,0x0e00, dea,2,1);\r
530 EaRead ( 0, 1, dea,2,0x0e00);\r
531\r
532 if (type==0) ot(" sub r1,r1,r10\n");\r
533 if (type==1) ot(" cmp r1,r10 ;@ Defines NZCV\n");\r
534 if (type==1) OpGetFlags(1,0); // Get Cmp flags\r
535 if (type==2) ot(" add r1,r1,r10\n");\r
536 ot("\n");\r
537 \r
538 if (type!=1) EaWrite( 0, 1, dea,2,0x0e00,1);\r
539\r
cfb3dfa0 540 OpEnd(sea);\r
cc68a136 541\r
542 return 0;\r
543}\r
544\r
545// --------------------- Opcodes 0x9100+ ---------------------\r
546// Emit a Subx/Addx opcode, 1t01ddd1 zz00rsss addx.z Ds,Dd\r
547int OpAddx(int op)\r
548{\r
549 int use=0;\r
550 int type=0,size=0,dea=0,sea=0,mem=0;\r
551\r
552 type=(op>>12)&5;\r
553 dea =(op>> 9)&7;\r
554 size=(op>> 6)&3; if (size>=3) return 1;\r
555 sea = op&7;\r
556 mem =(op>> 3)&1;\r
557\r
558 // See if we can do this opcode:\r
559 if (EaCanRead(sea,size)==0) return 1;\r
560 if (EaCanWrite(dea)==0) return 1;\r
561\r
562 if(mem) { sea+=0x20; dea+=0x20; }\r
563\r
564 use=op&~0x0e07; // Use same opcode for Dn\r
565 if (size==0&&(sea==0x27||dea==0x27)) use=op; // ___x.b -(a7)\r
566 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
567\r
cfb3dfa0 568 OpStart(op,sea,dea); Cycles=4;\r
cc68a136 569 if(size>=2) Cycles+=4;\r
570 if(sea>=0x10) Cycles+=2;\r
571\r
572 ot(";@ Get r10=EA r11=EA value\n");\r
573 EaCalc( 0,0x0007,sea,size,1);\r
574 EaRead( 0, 11,sea,size,0x0007,1);\r
575 ot(";@ Get r0=Register r1=Register value\n");\r
576 EaCalc( 0,0x0e00,dea,size,1);\r
577 EaRead( 0, 1,dea,size,0x0e00,1);\r
578\r
579 ot(";@ Do arithmetic:\n");\r
580 GetXBit(type==1);\r
581\r
582 if (type==5 && size<2)\r
583 {\r
584 ot(";@ Make sure the carry bit will tip the balance:\n");\r
a6785576 585 ot(" mvn r2,#0\n");\r
cc68a136 586 ot(" orr r11,r11,r2,lsr #%i\n",(size==0)?8:16);\r
587 ot("\n");\r
588 }\r
589\r
590 if (type==1) ot(" sbcs r1,r1,r11\n");\r
591 if (type==5) ot(" adcs r1,r1,r11\n");\r
592 ot(" orr r3,r9,#0xb0000000 ;@ for old Z\n");\r
593 OpGetFlags(type==1,1,0); // subtract\r
594 if (size<2) {\r
595 ot(" movs r2,r1,lsr #%i\n", size?16:24);\r
596 ot(" orreq r9,r9,#0x40000000 ;@ add potentially missed Z\n");\r
597 }\r
598 ot(" andeq r9,r9,r3 ;@ fix Z\n");\r
599 ot("\n");\r
600\r
601 ot(";@ Save result:\n");\r
602 EaWrite( 0, 1, dea,size,0x0e00,1);\r
603\r
cfb3dfa0 604 OpEnd(sea,dea);\r
cc68a136 605\r
606 return 0;\r
607}\r
608\r
609// --------------------- Opcodes 0xb000+ ---------------------\r
610// Emit a Cmp/Eor opcode, 1011rrrt xxeeeeee (rrr=Dn, t=cmp/eor, xx=size extension, eeeeee=ea)\r
611int OpCmpEor(int op)\r
612{\r
613 int rea=0,eor=0;\r
614 int size=0,ea=0,use=0;\r
615\r
616 // Get EA and register EA\r
617 rea=(op>>9)&7;\r
618 eor=(op>>8)&1;\r
619 size=(op>>6)&3; if (size>=3) return 1;\r
620 ea=op&0x3f;\r
621\r
622 if (eor && (ea>>3) == 1) return 1; // not a valid mode for eor\r
623\r
624 // See if we can do this opcode:\r
625 if (EaCanRead(ea,size)==0) return 1;\r
626 if (eor && EaCanWrite(ea)==0) return 1;\r
627 if (EaAn(ea)&&(eor||size==0)) return 1;\r
628\r
629 use=OpBase(op);\r
630 use&=~0x0e00; // Use 1 handler for register d0-7\r
631 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
632\r
a6785576 633 OpStart(op,ea); Cycles=4;\r
cc68a136 634 if(eor) {\r
635 if(ea>8) Cycles+=4;\r
636 if(size>=2) Cycles+=4;\r
637 } else {\r
638 if(size>=2) Cycles+=2;\r
639 }\r
640\r
641 ot(";@ Get EA into r10 and value into r0:\n");\r
642 EaCalc (10,0x003f, ea,size,1);\r
643 EaRead (10, 0, ea,size,0x003f,1);\r
644\r
645 ot(";@ Get register operand into r1:\n");\r
646 EaCalc (1, 0x0e00, rea,size,1);\r
647 EaRead (1, 1, rea,size,0x0e00,1);\r
648\r
649 ot(";@ Do arithmetic:\n");\r
650 if (eor==0) ot(" cmp r1,r0\n");\r
651 if (eor)\r
652 {\r
653 ot(" eor r1,r0,r1\n");\r
654 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
655 }\r
656\r
657 OpGetFlags(eor==0,0); // Cmp like subtract\r
658 ot("\n");\r
659\r
660 if (eor) EaWrite(10, 1,ea,size,0x003f,1);\r
661\r
cfb3dfa0 662 OpEnd(ea);\r
cc68a136 663 return 0;\r
664}\r
665\r
666// Emit a Cmpm opcode, 1011ddd1 xx001sss (rrr=Adst, xx=size extension, sss=Asrc)\r
667int OpCmpm(int op)\r
668{\r
669 int size=0,sea=0,dea=0,use=0;\r
670\r
671 // get size, get EAs\r
672 size=(op>>6)&3; if (size>=3) return 1;\r
673 sea=(op&7)|0x18;\r
674 dea=(op>>9)&0x3f;\r
675\r
676 use=op&~0x0e07; // Use 1 handler for all registers..\r
677 if (size==0&&(sea==0x1f||dea==0x1f)) use=op; // ..except (a7)+\r
678 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
679\r
a6785576 680 OpStart(op,sea); Cycles=4;\r
cc68a136 681\r
682 ot(";@ Get src operand into r10:\n");\r
683 EaCalc (0,0x000f, sea,size,1);\r
684 EaRead (0, 10, sea,size,0x000f,1);\r
685\r
686 ot(";@ Get dst operand into r0:\n");\r
687 EaCalc (0,0x1e00, dea,size,1);\r
688 EaRead (0, 0, dea,size,0x1e00,1);\r
689\r
690 ot(" cmp r0,r10\n");\r
691 OpGetFlags(1,0); // Cmp like subtract\r
692\r
cfb3dfa0 693 OpEnd(sea);\r
cc68a136 694 return 0;\r
695}\r
696\r
697\r
698// Emit a Chk opcode, 0100ddd1 x0eeeeee (rrr=Dn, x=size extension, eeeeee=ea)\r
699int OpChk(int op)\r
700{\r
701 int rea=0;\r
702 int size=0,ea=0,use=0;\r
703\r
704 // Get EA and register EA\r
705 rea=(op>>9)&7;\r
706 if((op>>7)&1)\r
707 size=1; // word operation\r
708 else size=2; // long\r
709 ea=op&0x3f;\r
710\r
711 if (EaAn(ea)) return 1; // not a valid mode\r
712 if (size!=1) return 1; // 000 variant only supports word\r
713\r
714 // See if we can do this opcode:\r
715 if (EaCanRead(ea,size)==0) return 1;\r
716\r
717 use=OpBase(op);\r
718 use&=~0x0e00; // Use 1 handler for register d0-7\r
719 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
720\r
a6785576 721 OpStart(op,ea); Cycles=10;\r
cc68a136 722\r
723 ot(";@ Get EA into r10 and value into r0:\n");\r
724 EaCalc (10,0x003f, ea,size,1);\r
725 EaRead (10, 0, ea,size,0x003f,1);\r
726\r
727 ot(";@ Get register operand into r1:\n");\r
728 EaCalc (1, 0x0e00, rea,size,1);\r
729 EaRead (1, 1, rea,size,0x0e00,1);\r
730\r
731 ot(";@ get flags, including undocumented ones\n");\r
732 ot(" and r3,r9,#0x80000000\n");\r
733 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
734 OpGetFlags(0,0);\r
735\r
736 ot(";@ is reg negative?\n");\r
737 ot(" bmi chktrap%.4x\n",op);\r
738\r
739 ot(";@ Do arithmetic:\n");\r
740 ot(" cmp r1,r0\n");\r
741 ot(" bicgt r9,r9,#0x80000000 ;@ N\n");\r
742 ot(" bgt chktrap%.4x\n",op);\r
743\r
744 ot(";@ old N remains\n");\r
745 ot(" bic r9,r9,#0x80000000 ;@ N\n");\r
746 ot(" orr r9,r9,r3\n");\r
cfb3dfa0 747 OpEnd(ea);\r
cc68a136 748\r
749 ot("chktrap%.4x%s ;@ CHK exception:\n",op,ms?"":":");\r
750 ot(" mov r0,#0x18\n");\r
751 ot(" bl Exception\n");\r
752 Cycles+=40;\r
cfb3dfa0 753 OpEnd(ea);\r
cc68a136 754\r
755 return 0;\r
756}\r
757\r