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