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