optimizations, bugfixes, uae works (but with timing glitches?)
[picodrive.git] / cpu / Cyclone / OpMove.cpp
CommitLineData
cc68a136 1\r
2#include "app.h"\r
3\r
4\r
5// Pack our flags into r1, in SR/CCR register format\r
6// trashes r0,r2\r
7void OpFlagsToReg(int high)\r
8{\r
85a36a57 9 ot(" ldr r0,[r7,#0x4c] ;@ X bit\n");\r
cc68a136 10 ot(" mov r1,r9,lsr #28 ;@ ____NZCV\n");\r
11 ot(" eor r2,r1,r1,ror #1 ;@ Bit 0=C^V\n");\r
12 ot(" tst r2,#1 ;@ 1 if C!=V\n");\r
13 ot(" eorne r1,r1,#3 ;@ ____NZVC\n");\r
14 ot("\n");\r
15 if (high) ot(" ldrb r2,[r7,#0x44] ;@ Include SR high\n");\r
85a36a57 16 ot(" and r0,r0,#0x20000000\n");\r
17 ot(" orr r1,r1,r0,lsr #25 ;@ ___XNZVC\n");\r
cc68a136 18 if (high) ot(" orr r1,r1,r2,lsl #8\n");\r
19 ot("\n");\r
20}\r
21\r
22// Convert SR/CRR register in r0 to our flags\r
23// trashes r0,r1\r
24void OpRegToFlags(int high)\r
25{\r
26 ot(" eor r1,r0,r0,ror #1 ;@ Bit 0=C^V\n");\r
85a36a57 27 ot(" mov r2,r0,lsl #25\n");\r
cc68a136 28 ot(" tst r1,#1 ;@ 1 if C!=V\n");\r
29 ot(" eorne r0,r0,#3 ;@ ___XNZCV\n");\r
85a36a57 30 ot(" str r2,[r7,#0x4c] ;@ Store X bit\n");\r
cc68a136 31 ot(" mov r9,r0,lsl #28 ;@ r9=NZCV...\n");\r
32\r
33 if (high)\r
34 {\r
35 ot(" mov r0,r0,ror #8\n");\r
36 ot(" and r0,r0,#0xa7 ;@ only take defined bits\n");\r
37 ot(" strb r0,[r7,#0x44] ;@ Store SR high\n");\r
38 }\r
39 ot("\n");\r
40}\r
41\r
85a36a57 42void SuperEnd(void)\r
cc68a136 43{\r
85a36a57 44 ot(";@ ----------\n");\r
45 ot(";@ tried execute privileged instruction in user mode\n");\r
46 ot("WrongPrivilegeMode%s\n",ms?"":":");\r
47 ot(" sub r4,r4,#2 ;@ last opcode wasn't executed - go back\n");\r
cc68a136 48 ot(" mov r0,#0x20 ;@ privilege violation\n");\r
49 ot(" bl Exception\n");\r
50 Cycles=34;\r
ee5e024c 51 OpEnd(0);\r
cc68a136 52}\r
53\r
54// does OSP and A7 swapping if needed\r
55// new or old SR (not the one already in [r7,#0x44]) should be passed in r11\r
85a36a57 56// trashes r0,r11\r
57void SuperChange(int op,int load_srh)\r
cc68a136 58{\r
59 ot(";@ A7 <-> OSP?\n");\r
85a36a57 60 if (load_srh)\r
61 ot(" ldr r0,[r7,#0x44] ;@ Get other SR high\n");\r
62 ot(" eor r0,r0,r11\n");\r
63 ot(" tst r0,#0x20\n");\r
cc68a136 64 ot(" beq no_sp_swap%.4x\n",op);\r
65 ot(" ;@ swap OSP and A7:\n");\r
66 ot(" ldr r11,[r7,#0x3C] ;@ Get A7\n");\r
85a36a57 67 ot(" ldr r0, [r7,#0x48] ;@ Get OSP\n");\r
cc68a136 68 ot(" str r11,[r7,#0x48]\n");\r
85a36a57 69 ot(" str r0, [r7,#0x3C]\n");\r
cc68a136 70 ot("no_sp_swap%.4x%s\n", op, ms?"":":");\r
71}\r
72\r
73\r
74\r
75// --------------------- Opcodes 0x1000+ ---------------------\r
76// Emit a Move opcode, 00xxdddd ddssssss\r
77int OpMove(int op)\r
78{\r
79 int sea=0,tea=0;\r
80 int size=0,use=0;\r
81 int movea=0;\r
82\r
83 // Get source and target EA\r
84 sea = op&0x003f;\r
85 tea =(op&0x01c0)>>3;\r
86 tea|=(op&0x0e00)>>9;\r
87\r
88 if (tea>=8 && tea<0x10) movea=1;\r
89\r
90 // Find size extension\r
91 switch (op&0x3000)\r
92 {\r
93 default: return 1;\r
94 case 0x1000: size=0; break;\r
95 case 0x3000: size=1; break;\r
96 case 0x2000: size=2; break;\r
97 }\r
98\r
99 if (size<1 && (movea || EaAn(sea))) return 1; // move.b An,* and movea.b * are invalid\r
100\r
101 // See if we can do this opcode:\r
102 if (EaCanRead (sea,size)==0) return 1;\r
103 if (EaCanWrite(tea )==0) return 1;\r
104\r
85a36a57 105 use=OpBase(op,size);\r
cc68a136 106 if (tea<0x38) use&=~0x0e00; // Use same handler for register ?0-7\r
107 \r
85a36a57 108 if (tea==0x1f || tea==0x27) use|=0x0e00; // Specific handler for (a7)+ and -(a7)\r
cc68a136 109\r
110 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
111\r
cfb3dfa0 112 OpStart(op,sea,tea); Cycles=4;\r
cc68a136 113\r
85a36a57 114 EaCalcRead(-1,1,sea,size,0x003f);\r
cc68a136 115\r
85a36a57 116 if (movea==0)\r
117 {\r
cc68a136 118 ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n");\r
119 ot(" mrs r9,cpsr ;@ r9=NZCV flags\n");\r
120 ot("\n");\r
121 }\r
122\r
123 if (movea) size=2; // movea always expands to 32-bits\r
124\r
cc68a136 125#if SPLIT_MOVEL_PD\r
126 if ((tea&0x38)==0x20 && size==2) { // -(An)\r
60305cdd 127 EaCalc (10,0x0e00,tea,size,0,0);\r
cc68a136 128 ot(" mov r11,r1\n");\r
85a36a57 129 ot(" add r0,r10,#2\n");\r
03c5768c 130 EaWrite(0, 1,tea,1,0x0e00,0,0);\r
131 EaWrite(10, 11,tea,1,0x0e00,1);\r
cc68a136 132 }\r
60305cdd 133 else\r
cc68a136 134#endif\r
60305cdd 135 {\r
136 EaCalc (0,0x0e00,tea,size,0,0);\r
137 EaWrite(0, 1,tea,size,0x0e00,0,0);\r
138 }\r
cc68a136 139\r
140#if CYCLONE_FOR_GENESIS && !MEMHANDLERS_CHANGE_CYCLES\r
141 // this is a bit hacky\r
142 if ((tea==0x39||(tea&0x38)==0x10)&&size>=1)\r
143 ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n");\r
144#endif\r
145\r
146 if((tea&0x38)==0x20) Cycles-=2; // less cycles when dest is -(An)\r
147\r
cfb3dfa0 148 OpEnd(sea,tea);\r
cc68a136 149 return 0;\r
150}\r
151\r
152// --------------------- Opcodes 0x41c0+ ---------------------\r
153// Emit an Lea opcode, 0100nnn1 11aaaaaa\r
154int OpLea(int op)\r
155{\r
156 int use=0;\r
157 int sea=0,tea=0;\r
158\r
159 sea= op&0x003f;\r
160 tea=(op&0x0e00)>>9; tea|=8;\r
161\r
162 if (EaCanRead(sea,-1)==0) return 1; // See if we can do this opcode\r
163\r
85a36a57 164 use=OpBase(op,0);\r
cc68a136 165 use&=~0x0e00; // Also use 1 handler for target ?0-7\r
166 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
167\r
cfb3dfa0 168 OpStart(op,sea,tea);\r
cc68a136 169\r
170 EaCalc (1,0x003f,sea,0); // Lea\r
03c5768c 171 EaCalc (0,0x0e00,tea,2);\r
172 EaWrite(0, 1,tea,2,0x0e00);\r
cc68a136 173\r
174 Cycles=Ea_add_ns(g_lea_cycle_table,sea);\r
175\r
cfb3dfa0 176 OpEnd(sea,tea);\r
cc68a136 177\r
178 return 0;\r
179}\r
180\r
181// --------------------- Opcodes 0x40c0+ ---------------------\r
182// Move SR opcode, 01000tt0 11aaaaaa move SR\r
183int OpMoveSr(int op)\r
184{\r
185 int type=0,ea=0;\r
186 int use=0,size=1;\r
187\r
188 type=(op>>9)&3; // from SR, from CCR, to CCR, to SR\r
189 ea=op&0x3f;\r
190\r
191 if(EaAn(ea)) return 1; // can't use An regs\r
192\r
193 switch(type)\r
194 {\r
195 case 0:\r
196 if (EaCanWrite(ea)==0) return 1; // See if we can do this opcode:\r
197 break;\r
198\r
199 case 1:\r
200 return 1; // no such op in 68000\r
201\r
a6785576 202 case 2: case 3:\r
cc68a136 203 if (EaCanRead(ea,size)==0) return 1; // See if we can do this opcode:\r
204 break;\r
205 }\r
206\r
85a36a57 207 use=OpBase(op,size);\r
cc68a136 208 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
209\r
ee5e024c 210 // 68000 model allows reading whole SR in user mode (but newer models don't)\r
211 OpStart(op,ea,0,0,type==3);\r
cc68a136 212 Cycles=12;\r
213 if (type==0) Cycles=(ea>=8)?8:6;\r
214\r
cc68a136 215 if (type==0 || type==1)\r
216 {\r
217 OpFlagsToReg(type==0);\r
b637c56a 218 EaCalc (0,0x003f,ea,size,0,0);\r
219 EaWrite(0, 1,ea,size,0x003f,0,0);\r
cc68a136 220 }\r
221\r
222 if (type==2 || type==3)\r
223 {\r
85a36a57 224 EaCalcReadNoSE(-1,0,ea,size,0x003f);\r
cc68a136 225 OpRegToFlags(type==3);\r
226 if (type==3) {\r
85a36a57 227 SuperChange(op,0);\r
a6785576 228 }\r
cc68a136 229 }\r
230\r
ee5e024c 231 OpEnd(ea,0,0,type==3);\r
cc68a136 232\r
cc68a136 233 return 0;\r
234}\r
235\r
236\r
237// Ori/Andi/Eori $nnnn,sr 0000t0t0 01111100\r
238int OpArithSr(int op)\r
239{\r
240 int type=0,ea=0;\r
241 int use=0,size=0;\r
242\r
243 type=(op>>9)&5; if (type==4) return 1;\r
244 size=(op>>6)&1; // ccr or sr?\r
245 ea=0x3c;\r
246\r
85a36a57 247 use=OpBase(op,size);\r
cc68a136 248 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
249\r
ee5e024c 250 OpStart(op,ea,0,0,size!=0); Cycles=16;\r
cc68a136 251\r
b637c56a 252 EaCalc(10,0x003f,ea,size);\r
253 EaRead(10, 10,ea,size,0x003f);\r
cc68a136 254\r
255 OpFlagsToReg(size);\r
256 if (type==0) ot(" orr r0,r1,r10\n");\r
257 if (type==1) ot(" and r0,r1,r10\n");\r
258 if (type==5) ot(" eor r0,r1,r10\n");\r
259 OpRegToFlags(size);\r
ee5e024c 260 if (size && type!=0) { // we can't enter supervisor mode, nor unmask irqs just by using OR\r
85a36a57 261 SuperChange(op,0);\r
cc68a136 262 }\r
263\r
ee5e024c 264 OpEnd(ea,0,0,size!=0 && type!=0);\r
cc68a136 265\r
266 return 0;\r
267}\r
268\r
269// --------------------- Opcodes 0x4850+ ---------------------\r
270// Emit an Pea opcode, 01001000 01aaaaaa\r
271int OpPea(int op)\r
272{\r
273 int use=0;\r
274 int ea=0;\r
275\r
276 ea=op&0x003f; if (ea<0x10) return 1; // Swap opcode\r
277 if (EaCanRead(ea,-1)==0) return 1; // See if we can do this opcode:\r
278\r
85a36a57 279 use=OpBase(op,0);\r
cc68a136 280 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
281\r
a6785576 282 OpStart(op,ea);\r
cc68a136 283\r
284 ot(" ldr r10,[r7,#0x3c]\n");\r
285 EaCalc (1,0x003f, ea,0);\r
286 ot("\n");\r
287 ot(" sub r0,r10,#4 ;@ Predecrement A7\n");\r
288 ot(" str r0,[r7,#0x3c] ;@ Save A7\n");\r
289 ot("\n");\r
290 MemHandler(1,2); // Write 32-bit\r
291 ot("\n");\r
292\r
293 Cycles=6+Ea_add_ns(g_pea_cycle_table,ea);\r
294\r
cfb3dfa0 295 OpEnd(ea);\r
cc68a136 296\r
297 return 0;\r
298}\r
299\r
300// --------------------- Opcodes 0x4880+ ---------------------\r
301// Emit a Movem opcode, 01001d00 1xeeeeee regmask\r
302int OpMovem(int op)\r
303{\r
304 int size=0,ea=0,cea=0,dir=0;\r
305 int use=0,decr=0,change=0;\r
306\r
307 size=((op>>6)&1)+1; // word, long\r
308 ea=op&0x003f;\r
309 dir=(op>>10)&1; // Direction (1==ea2reg)\r
310\r
311 if (dir) {\r
312 if (ea<0x10 || ea>0x3b || (ea&0x38)==0x20) return 1; // Invalid EA\r
313 } else {\r
314 if (ea<0x10 || ea>0x39 || (ea&0x38)==0x18) return 1;\r
315 }\r
316\r
317 if ((ea&0x38)==0x18 || (ea&0x38)==0x20) change=1;\r
318 if ((ea&0x38)==0x20) decr=1; // -(An), bitfield is decr\r
319\r
320 cea=ea; if (change) cea=0x10;\r
321\r
85a36a57 322 use=OpBase(op,size);\r
cc68a136 323 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
324\r
ee5e024c 325 OpStart(op,ea,0,1);\r
cc68a136 326\r
cc68a136 327 ot(" ldrh r11,[r4],#2 ;@ r11=register mask\n");\r
328\r
cc68a136 329 ot(";@ r10=Register Index*4:\n");\r
b637c56a 330 if (decr) ot(" mov r10,#0x40 ;@ order reversed for -(An)\n");\r
331 else ot(" mov r10,#-4\n");\r
cc68a136 332 \r
333 ot("\n");\r
b637c56a 334 ot(";@ Get the address into r6:\n");\r
335 EaCalc(6,0x003f,cea,size);\r
cc68a136 336\r
cc68a136 337 ot("\n");\r
b637c56a 338 ot(" tst r11,r11\n"); // sanity check\r
339 ot(" beq NoRegs%.4x\n",op);\r
cc68a136 340\r
b637c56a 341 ot("\n");\r
342 ot("Movemloop%.4x%s\n",op, ms?"":":");\r
343 ot(" add r10,r10,#%d ;@ r10=Next Register\n",decr?-4:4);\r
344 ot(" movs r11,r11,lsr #1\n");\r
345 ot(" bcc Movemloop%.4x\n",op);\r
346 ot("\n");\r
347\r
348 if (decr) ot(" sub r6,r6,#%d ;@ Pre-decrement address\n",1<<size);\r
cc68a136 349\r
350 if (dir)\r
351 {\r
352 ot(" ;@ Copy memory to register:\n",1<<size);\r
b637c56a 353 EaRead (6,0,ea,size,0x003f);\r
cc68a136 354 ot(" str r0,[r7,r10] ;@ Save value into Dn/An\n");\r
355 }\r
356 else\r
357 {\r
ee5e024c 358 // if (size == 2 && decr && SPLIT_MOVEL_PD) we should do 2xWrite16 here\r
359 // (same as in movel.l ?, -(An)), but as this is not likely to be needed and\r
360 // we do not want the performance hit, we do single Write32 instead.\r
cc68a136 361 ot(" ;@ Copy register to memory:\n",1<<size);\r
362 ot(" ldr r1,[r7,r10] ;@ Load value from Dn/An\n");\r
b637c56a 363 EaWrite(6,1,ea,size,0x003f);\r
cc68a136 364 }\r
365\r
b637c56a 366 if (decr==0) ot(" add r6,r6,#%d ;@ Post-increment address\n",1<<size);\r
cc68a136 367\r
368 ot(" sub r5,r5,#%d ;@ Take some cycles\n",2<<size);\r
b637c56a 369 ot(" tst r11,r11\n");\r
370 ot(" bne Movemloop%.4x\n",op);\r
cc68a136 371 ot("\n");\r
372\r
373 if (change)\r
374 {\r
375 ot(";@ Write back address:\n");\r
376 EaCalc (0,0x0007,8|(ea&7),2);\r
b637c56a 377 EaWrite(0, 6,8|(ea&7),2,0x0007);\r
cc68a136 378 }\r
379\r
b637c56a 380 ot("NoRegs%.4x%s\n",op, ms?"":":");\r
381 ot(" ldr r6,=CycloneJumpTab ;@ restore Opcode Jump table\n");\r
cc68a136 382 ot("\n");\r
383\r
384 if(dir) { // er\r
385 if (ea==0x3a) Cycles=16; // ($nn,PC)\r
386 else if (ea==0x3b) Cycles=18; // ($nn,pc,Rn)\r
a6785576 387 else Cycles=12;\r
cc68a136 388 } else {\r
389 Cycles=8;\r
390 }\r
391\r
392 Cycles+=Ea_add_ns(g_movem_cycle_table,ea);\r
393\r
ee5e024c 394 OpEnd(ea,0,1);\r
b637c56a 395 ltorg();\r
3a5e6cf8 396 ot("\n");\r
cc68a136 397\r
398 return 0;\r
399}\r
400\r
401// --------------------- Opcodes 0x4e60+ ---------------------\r
402// Emit a Move USP opcode, 01001110 0110dnnn move An to/from USP\r
403int OpMoveUsp(int op)\r
404{\r
405 int use=0,dir=0;\r
406\r
407 dir=(op>>3)&1; // Direction\r
408 use=op&~0x0007; // Use same opcode for all An\r
409\r
410 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
411\r
ee5e024c 412 OpStart(op,0,0,0,1); Cycles=4;\r
cc68a136 413\r
414 if (dir)\r
415 {\r
416 ot(" ldr r1,[r7,#0x48] ;@ Get from USP\n\n");\r
85a36a57 417 EaCalc (0,0x000f,8,2,1);\r
418 EaWrite(0, 1,8,2,0x000f,1);\r
cc68a136 419 }\r
420 else\r
421 {\r
85a36a57 422 EaCalc (0,0x000f,8,2,1);\r
423 EaRead (0, 0,8,2,0x000f,1);\r
cc68a136 424 ot(" str r0,[r7,#0x48] ;@ Put in USP\n\n");\r
425 }\r
426 \r
427 OpEnd();\r
428\r
cc68a136 429 return 0;\r
430}\r
431\r
432// --------------------- Opcodes 0x7000+ ---------------------\r
433// Emit a Move Quick opcode, 0111nnn0 dddddddd moveq #dd,Dn\r
434int OpMoveq(int op)\r
435{\r
436 int use=0;\r
437\r
438 use=op&0xf100; // Use same opcode for all values\r
439 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
440\r
441 OpStart(op); Cycles=4;\r
442\r
443 ot(" movs r0,r8,asl #24\n");\r
444 ot(" and r1,r8,#0x0e00\n");\r
445 ot(" mov r0,r0,asr #24 ;@ Sign extended Quick value\n");\r
446 ot(" mrs r9,cpsr ;@ r9=NZ flags\n");\r
447 ot(" str r0,[r7,r1,lsr #7] ;@ Store into Dn\n");\r
448 ot("\n");\r
449\r
450 OpEnd();\r
451\r
452 return 0;\r
453}\r
454\r
455// --------------------- Opcodes 0xc140+ ---------------------\r
456// Emit a Exchange opcode:\r
457// 1100ttt1 01000sss exg ds,dt\r
458// 1100ttt1 01001sss exg as,at\r
459// 1100ttt1 10001sss exg as,dt\r
460int OpExg(int op)\r
461{\r
462 int use=0,type=0;\r
463\r
464 type=op&0xf8;\r
465\r
466 if (type!=0x40 && type!=0x48 && type!=0x88) return 1; // Not an exg opcode\r
467\r
468 use=op&0xf1f8; // Use same opcode for all values\r
469 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler\r
470\r
471 OpStart(op); Cycles=6;\r
472\r
473 ot(" and r10,r8,#0x0e00 ;@ Find T register\n");\r
474 ot(" and r11,r8,#0x000f ;@ Find S register\n");\r
475 if (type==0x48) ot(" orr r10,r10,#0x1000 ;@ T is an address register\n");\r
476 ot("\n");\r
477 ot(" ldr r0,[r7,r10,lsr #7] ;@ Get T\n");\r
478 ot(" ldr r1,[r7,r11,lsl #2] ;@ Get S\n");\r
479 ot("\n");\r
480 ot(" str r0,[r7,r11,lsl #2] ;@ T->S\n");\r
481 ot(" str r1,[r7,r10,lsr #7] ;@ S->T\n"); \r
482 ot("\n");\r
483\r
484 OpEnd();\r
485 \r
486 return 0;\r
487}\r
488\r
489// ------------------------- movep -------------------------------\r
490// 0000ddd1 0z001sss\r
491// 0000sss1 1z001ddd (to mem)\r
492int OpMovep(int op)\r
493{\r
85a36a57 494 int ea=0,rea=0;\r
495 int size=1,use=0,dir,aadd=0;\r
cc68a136 496\r
497 use=op&0xf1f8;\r
498 if (op!=use) { OpUse(op,use); return 0; } // Use existing handler (for all dests, srcs)\r
499\r
500 // Get EA\r
501 ea = (op&0x0007)|0x28;\r
03c5768c 502 rea= (op&0x0e00)>>9;\r
cc68a136 503 dir = (op>>7)&1;\r
504\r
505 // Find size extension\r
506 if(op&0x0040) size=2;\r
507\r
a6785576 508 OpStart(op,ea);\r
cc68a136 509 \r
510 if(dir) { // reg to mem\r
03c5768c 511 EaCalcReadNoSE(-1,11,rea,size,0x0e00);\r
85a36a57 512\r
513 EaCalc(10,0x000f,ea,size);\r
a6785576 514 if(size==2) { // if operand is long\r
515 ot(" mov r1,r11,lsr #24 ;@ first byte\n");\r
85a36a57 516 EaWrite(10,1,ea,0,0x000f); // store first byte\r
517 ot(" add r0,r10,#%i\n",(aadd+=2));\r
a6785576 518 ot(" mov r1,r11,lsr #16 ;@ second byte\n");\r
85a36a57 519 EaWrite(0,1,ea,0,0x000f); // store second byte\r
520 ot(" add r0,r10,#%i\n",(aadd+=2));\r
521 } else {\r
522 ot(" mov r0,r10\n");\r
a6785576 523 }\r
524 ot(" mov r1,r11,lsr #8 ;@ first or third byte\n");\r
85a36a57 525 EaWrite(0,1,ea,0,0x000f);\r
526 ot(" add r0,r10,#%i\n",(aadd+=2));\r
a6785576 527 ot(" and r1,r11,#0xff\n");\r
85a36a57 528 EaWrite(0,1,ea,0,0x000f);\r
cc68a136 529 } else { // mem to reg\r
85a36a57 530 EaCalc(10,0x000f,ea,size,1);\r
531 EaRead(10,11,ea,0,0x000f,1); // read first byte\r
532 ot(" add r0,r10,#2\n");\r
533 EaRead(0,1,ea,0,0x000f,1); // read second byte\r
a6785576 534 if(size==2) { // if operand is long\r
cc68a136 535 ot(" orr r11,r11,r1,lsr #8 ;@ second byte\n");\r
85a36a57 536 ot(" add r0,r10,#4\n");\r
537 EaRead(0,1,ea,0,0x000f,1);\r
cc68a136 538 ot(" orr r11,r11,r1,lsr #16 ;@ third byte\n");\r
85a36a57 539 ot(" add r0,r10,#6\n");\r
540 EaRead(0,1,ea,0,0x000f,1);\r
541 ot(" orr r1,r11,r1,lsr #24 ;@ fourth byte\n");\r
a6785576 542 } else {\r
85a36a57 543 ot(" orr r1,r11,r1,lsr #8 ;@ second byte\n");\r
a6785576 544 }\r
545 // store the result\r
85a36a57 546 EaCalc(11,0x0e00,rea,size,1); // reg number -> r11\r
547 EaWrite(11,1,rea,size,0x0e00,1);\r
cc68a136 548 }\r
549\r
550 Cycles=(size==2)?24:16;\r
cfb3dfa0 551 OpEnd(ea);\r
cc68a136 552\r
553 return 0;\r
554}\r
555\r
556// Emit a Stop/Reset opcodes, 01001110 011100t0 imm\r
557int OpStopReset(int op)\r
558{\r
85a36a57 559 int type=(op>>1)&1; // stop/reset\r
cc68a136 560\r
ee5e024c 561 OpStart(op,0,0,0,1);\r
cc68a136 562\r
563 if(type) {\r
564 // copy immediate to SR, stop the CPU and eat all remaining cycles.\r
565 ot(" ldrh r0,[r4],#2 ;@ Fetch the immediate\n");\r
cc68a136 566 OpRegToFlags(1);\r
85a36a57 567 SuperChange(op,0);\r
cc68a136 568\r
a6785576 569 ot("\n");\r
cc68a136 570\r
a6785576 571 ot(" mov r0,#1\n");\r
572 ot(" str r0,[r7,#0x58] ;@ stopped\n");\r
573 ot("\n");\r
cc68a136 574\r
a6785576 575 ot(" mov r5,#0 ;@ eat cycles\n");\r
cc68a136 576 Cycles = 4;\r
a6785576 577 ot("\n");\r
cc68a136 578 }\r
579 else\r
580 {\r
581 Cycles = 132;\r
582#if USE_RESET_CALLBACK\r
583 ot(" str r4,[r7,#0x40] ;@ Save PC\n");\r
584 ot(" mov r1,r9,lsr #28\n");\r
585 ot(" strb r1,[r7,#0x46] ;@ Save Flags (NZCV)\n");\r
586 ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");\r
587 ot(" ldr r11,[r7,#0x90] ;@ ResetCallback\n");\r
588 ot(" tst r11,r11\n");\r
589 ot(" movne lr,pc\n");\r
85a36a57 590 ot(" bxne r11 ;@ call ResetCallback if it is defined\n");\r
cc68a136 591 ot(" ldrb r9,[r7,#0x46] ;@ r9 = Load Flags (NZCV)\n");\r
592 ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n");\r
593 ot(" ldr r4,[r7,#0x40] ;@ Load PC\n");\r
594 ot(" mov r9,r9,lsl #28\n");\r
85a36a57 595 ot("\n");\r
cc68a136 596#endif\r
597 }\r
598\r
599 OpEnd();\r
cc68a136 600\r
601 return 0;\r
602}\r
cfb3dfa0 603\r