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