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