|
|
1.1 root 1: /*
2: * UAE - The Unusable Amiga Emulator
3: *
4: * MC68000 emulation v0.5
5: *
6: * v0.0: 950227
7: * instruction decoding, emulate all instructions except MOVEM and
8: * things like MOVE SR,EA or RESET
9: * debugging functions: disasm, dumpstate
10: * v0.1: 950228
11: * exceptions, almost all instructions, bug fixes
12: * v0.2: 950305
13: * more bug fixes in interrupt code. STOP implemented. Bugs in
14: * GenerateDecTab() fixed.
15: * v0.3: 950306
16: * bug fixes: ROR shouldn't set X flag. SWAP didn't set any flags.
17: * GenerateDecTab() created wrong sizes for all shift instructions
18: * v0.4: 950309
19: * yet another bug in the shifting instructions part of GenerateDecTab
20: * v0.5: 930311
21: * lots of bug fixes. Sign extension is probably correct now.
22: * Multiplication corrected. None of these bugs affected the Kickstart.
23: *
24: * (c) 1995 Bernd Schmidt
25: *
26: */
27:
28: #include <iostream.h>
29: #include <iomanip.h>
30: #include <assert.h>
31: #include <string.h>
32:
33: #include "amiga.h"
34: #include "memory.h"
35: #include "custom.h"
36: #include "cpu.h"
37:
38: enum amodes {
39: Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
40: absw, absl, PC16, PC8r, imm, imm3, ill2, ill3
41: };
42:
43: class addr_mode {
44: public:
45: amodes mode;
46: UBYTE reg;
47: addr_mode(int=0,int=0);
48: };
49:
50: addr_mode::addr_mode(int m,int r)
51: {
52: assert ((r & 7) == r);
53: assert ((m & 7) == m);
54:
55: if (m == 7) mode = (amodes)(absw + r);
56: else mode = (amodes)m;
57: reg = r;
58: }
59:
60: enum eatypes {
61: RegD, RegA, Addr, EAIM
62: };
63:
64: struct effadr {
65: public:
66: ULONG addr;
67: eatypes type;
68: ULONG szmask;
69: };
70:
71: struct instr_params {
72: addr_mode src,dest;
73: ULONG mask;
74: UWORD clogs;
75: };
76:
77: typedef void instr_result;
78: typedef instr_result (*instr_func)(const instr_params &);
79:
80: struct I_dec_tab_entry {
81: instr_func execfunc;
82: instr_params params;
83: I_dec_tab_entry() { execfunc = NULL; }
84: };
85:
86: static I_dec_tab_entry instr_dectab[65536];
87:
88: static void GenerateDecTab();
89:
90: void MC68000_init()
91: {
92: GenerateDecTab();
93: };
94:
95: typedef int flagtype; // faster than char ?
96:
97: static struct {
98: ULONG d[8];
99: CPTR a[8],usp;
100: UWORD sr;
101: flagtype t,s,x,n,z,v,c,stopped;
102: int intmask;
103: ULONG pc;
104: } regs;
105:
106: static ULONG sizemask(const int sz)
107: {
108: switch(sz){
109: case 0: return 0xff;
110: case 1: return 0xffff;
111: case 2: return 0xffffffff;
112: default: abort();
113: }
114: }
115:
116: static inline int mask2len(const ULONG mask)
117: {
118: if (mask == 0xff) return 1;
119: if (mask == 0xffff) return 2;
120: return 4;
121: }
122:
123: static inline int mask2shift(const ULONG mask)
124: {
125: if (mask == 0xff) return 7;
126: if (mask == 0xffff) return 15;
127: return 31;
128: }
129:
130: static inline ULONG ExtendWord(const ULONG v)
131: {
132: return (LONG)(WORD)(v);
133: }
134:
135: static inline ULONG ExtendByte(const ULONG v)
136: {
137: return (LONG)(BYTE)(v);
138: }
139:
140: static inline ULONG Extend(const ULONG v,const ULONG mask)
141: {
142: switch(mask){
143: case 0xff:
144: return (LONG)(BYTE)v;
145: case 0xffff:
146: return (LONG)(WORD)v;
147: default:
148: return v;
149: }
150: }
151:
152: static inline UWORD nextiword()
153: {
154: UWORD r = mem.get_word(regs.pc);
155: regs.pc += 2;
156: return r;
157: }
158:
159: static inline ULONG nextilong()
160: {
161: ULONG r = (mem.get_word(regs.pc) << 16) + mem.get_word(regs.pc+2);
162: regs.pc += 4;
163: return r;
164: }
165:
166: static effadr GetEA(const addr_mode &a, const ULONG mask)
167: {
168: effadr ea;
169: UWORD dp;
170: BYTE disp8;
171: int r;
172: ULONG dispreg;
173:
174: ea.szmask = mask;
175: switch(a.mode){
176: case Dreg:
177: ea.addr = a.reg; ea.type = RegD; break;
178: case Areg:
179: ea.addr = a.reg; ea.type = RegA; break;
180: case Aind:
181: ea.addr = regs.a[a.reg]; ea.type = Addr; break;
182: case Aipi:
183: ea.addr = regs.a[a.reg]; regs.a[a.reg] += mask2len(mask);
184: ea.type = Addr; break;
185: case Apdi:
186: ea.addr = regs.a[a.reg] -= mask2len(mask); ea.type = Addr; break;
187: case Ad16:
188: ea.addr = regs.a[a.reg] + (WORD)nextiword(); // cast for signed rel. values
189: ea.type = Addr; break;
190: case Ad8r:
191: dp = nextiword();
192: disp8 = dp & 0xFF;
193: r = (dp & 0x7000) >> 12;
194: dispreg = dp & 0x8000 ? regs.a[r] : regs.d[r];
195:
196: if (!(dp & 0x800)) dispreg = ExtendWord(dispreg);
197: ea.addr = regs.a[a.reg] + disp8 + dispreg;
198: ea.type = Addr; break;
199: case PC16:
200: ea.addr = regs.pc;
201: ea.addr += (WORD)nextiword(); // cast for signed rel. values
202: ea.type = Addr; break;
203: case PC8r:
204: ea.addr = regs.pc;
205: dp = nextiword();
206: disp8 = dp & 0xFF;
207: r = (dp & 0x7000) >> 12;
208: dispreg = dp & 0x8000 ? regs.a[r] : regs.d[r];
209:
210: if (!(dp & 0x800)) dispreg = ExtendWord(dispreg);
211: ea.addr += disp8 + dispreg;
212: ea.type = Addr; break;
213: case absw:
214: ea.type = Addr;
215: ea.addr = nextiword();
216: break;
217: case absl:
218: ea.type = Addr;
219: ea.addr = nextilong();
220: break;
221: case imm:
222: switch(mask){
223: case 0xff:
224: ea.addr = ExtendByte(nextiword()); ea.type = EAIM; break;
225: case 0xffff:
226: ea.addr = ExtendWord(nextiword()); ea.type = EAIM; break;
227: case 0xffffffff:
228: ea.addr = nextilong(); ea.type = EAIM; break;
229: }
230: break;
231: case imm3:
232: ea.addr = a.reg; ea.type = EAIM; break;
233: default:
234: abort(); // FIXME
235: }
236: return ea;
237: }
238:
239: static effadr MGetEA(const addr_mode &a, const ULONG mask)
240: {
241: effadr ea;
242: UWORD dp;
243: BYTE disp8;
244: int r;
245: ULONG dispreg;
246:
247: ea.szmask = mask;
248: switch(a.mode){
249: case Aind: case Aipi: case Apdi:
250: ea.addr = regs.a[a.reg]; ea.type = Addr; break;
251: case Ad16:
252: ea.addr = regs.a[a.reg] + (WORD)nextiword(); // cast for signed rel. values
253: ea.type = Addr; break;
254: case Ad8r:
255: dp = nextiword();
256: disp8 = dp & 0xFF;
257: r = (dp & 0x7000) >> 12;
258: dispreg = dp & 0x8000 ? regs.a[r] : regs.d[r];
259:
260: if (!(dp & 0x800)) dispreg = ExtendWord(dispreg);
261: ea.addr = regs.a[a.reg] + disp8 + dispreg;
262: ea.type = Addr; break;
263: case PC16:
264: ea.addr = regs.pc;
265: ea.addr += (WORD)nextiword(); // cast for signed rel. values
266: ea.type = Addr; break;
267: case PC8r:
268: ea.addr = regs.pc;
269: dp = nextiword();
270: disp8 = dp & 0xFF;
271: r = (dp & 0x7000) >> 12;
272: dispreg = dp & 0x8000 ? regs.a[r] : regs.d[r];
273:
274: if (!(dp & 0x800)) dispreg = ExtendWord(dispreg);
275: ea.addr += disp8 + dispreg;
276: ea.type = Addr; break;
277: case absw:
278: ea.type = Addr;
279: ea.addr = nextiword();
280: break;
281: case absl:
282: ea.type = Addr;
283: ea.addr = nextilong();
284: break;
285: default:
286: abort(); // FIXME
287: }
288: return ea;
289: }
290:
291: static void MCompleteEAFromRL(effadr &ea, const addr_mode &a, ULONG mask, UWORD bitmask)
292: {
293: int bitcnt = 0;
294: for(int i=0;i<16;i++) {
295: bitcnt += bitmask & 1;
296: bitmask >>= 1;
297: }
298: switch(a.mode){
299: case Aipi:
300: abort(); break;
301: case Apdi:
302: ea.addr = regs.a[a.reg] -= bitcnt * mask2len(mask); break;
303: default: break;
304: }
305: }
306:
307: static void MCompleteEAToRL(effadr &ea, const addr_mode &a, ULONG mask, UWORD bitmask)
308: {
309: int bitcnt = 0;
310: for(int i=0;i<16;i++) {
311: bitcnt += bitmask & 1;
312: bitmask >>= 1;
313: }
314: switch(a.mode){
315: case Aipi:
316: regs.a[a.reg] = ea.addr; break;
317: case Apdi:
318: abort(); break;
319: default: break;
320: }
321: }
322:
323: static ULONG RetrieveEA(const effadr &ea)
324: {
325: switch(ea.type){
326: case Addr:
327: return ea.addr;
328: default:
329: abort(); // FIXME
330: }
331: }
332:
333: static ULONG GetFromEA(const effadr &ea)
334: {
335: switch(ea.type) {
336: case RegD:
337: return Extend(regs.d[ea.addr],ea.szmask);
338: case RegA:
339: return Extend(regs.a[ea.addr],ea.szmask);
340: case Addr:
341: switch(ea.szmask){
342: case 0xff:
343: return ExtendByte(mem.get_byte(ea.addr));
344: case 0xffff:
345: return ExtendWord(mem.get_word(ea.addr));
346: default: // long
347: return (mem.get_word(ea.addr) << 16) + mem.get_word(ea.addr+2);
348: }
349: case EAIM:
350: return ea.addr;
351: }
352: }
353:
354: static void StoreToEA(const effadr &ea, const ULONG value)
355: {
356: switch(ea.type){
357: case RegD:
358: regs.d[ea.addr] &= ~ea.szmask; regs.d[ea.addr] |= (value & ea.szmask);
359: break;
360: case RegA:
361: regs.a[ea.addr] = value;
362: // if (ea.szmask == 0xffff) regs.a[ea.addr] = ExtendWord(regs.a[ea.addr]);
363: break;
364: case Addr:
365: switch(ea.szmask){
366: case 0xff:
367: mem.put_byte(ea.addr,value);
368: break;
369: case 0xffff:
370: mem.put_word(ea.addr,value);
371: break;
372: default: // long
373: mem.put_word(ea.addr,value >> 16);
374: mem.put_word(ea.addr+2, value & 0xffff);
375: }
376: break;
377: default:
378: cout << hex << regs.pc;
379: abort(); // FIXME
380: }
381: }
382:
383: static effadr ShowEA(addr_mode a,ULONG mask)
384: {
385: effadr ea;
386: UWORD dp;
387: BYTE disp8;
388: WORD disp16;
389: int r;
390: ULONG dispreg;
391:
392: cout << setw(1) << setfill('0');
393: ea.szmask = mask;
394: switch(a.mode){
395: case Dreg:
396: ea.addr = a.reg; ea.type = RegD;
397: cout << "D" << (int)a.reg;
398: break;
399: case Areg:
400: ea.addr = a.reg; ea.type = RegA;
401: cout << "A" << (int)a.reg;
402: break;
403: case Aind:
404: ea.addr = regs.a[a.reg]; ea.type = Addr;
405: cout << "(A" << (int)a.reg << ")";
406: break;
407: case Aipi:
408: ea.addr = regs.a[a.reg];
409: ea.type = Addr;
410: cout << "(A" << (int)a.reg << ")+";
411: break;
412: case Apdi:
413: ea.addr = regs.a[a.reg] - mask2len(mask); ea.type = Addr;
414: cout << "-(A" << (int)a.reg << ")";
415: break;
416: case Ad16:
417: disp16 = nextiword();
418: ea.addr = regs.a[a.reg] + (WORD)disp16;
419: ea.type = Addr;
420: cout << "(A" << (int)a.reg << ",$" << hex << setw(8) << disp16 << ") == $"
421: << ea.addr << dec;
422: break;
423: case Ad8r:
424: dp = nextiword();
425: disp8 = dp & 0xFF;
426: r = (dp & 0x7000) >> 12;
427: dispreg = dp & 0x8000 ? regs.a[r] : regs.d[r];
428:
429: if (!(dp & 0x800)) dispreg = ExtendWord(dispreg);
430: ea.addr = regs.a[a.reg] + disp8 + dispreg;
431: ea.type = Addr;
432: cout << "(A" << (int)a.reg << "," << ((dp & 0x8000) ? "A" : "D") << (int)r
433: << ",$" << hex << (int)disp8 << ") == $" << ea.addr
434: << dec;
435: break;
436: case PC16:
437: ea.addr = regs.pc;
438: disp16 = nextiword();
439: ea.addr += (WORD)disp16; // cast for signed rel. values
440: ea.type = Addr;
441: cout << "(PC" << ",$" << hex << setw(8) << disp16 << ") == $" << ea.addr
442: << dec;
443: break;
444: case PC8r:
445: ea.addr = regs.pc;
446: dp = nextiword();
447: disp8 = dp & 0xFF;
448: r = (dp & 0x7000) >> 12;
449: dispreg = dp & 0x8000 ? regs.a[r] : regs.d[r];
450:
451: if (!(dp & 0x800)) dispreg = ExtendWord(dispreg);
452: ea.addr += disp8 + dispreg;
453: ea.type = Addr;
454: cout << "(PC" << "," << ((dp & 0x8000) ? "A" : "D") << (int)r
455: << ",$" << hex << (int)disp8 << ") == $" << ea.addr
456: << dec;
457: break;
458: case absw:
459: ea.type = Addr;
460: ea.addr = nextiword();
461: cout << "$" << hex << ea.addr << dec;
462: break;
463: case absl:
464: ea.type = Addr;
465: ea.addr = nextilong();
466: cout << "$" << hex << ea.addr << dec;
467: break;
468: case imm:
469: switch(mask){
470: case 0xff:
471: ea.addr = nextiword() & 0xff; ea.type = EAIM; break;
472: case 0xffff:
473: ea.addr = nextiword(); ea.type = EAIM; break;
474: case 0xffffffff:
475: ea.addr = nextilong(); ea.type = EAIM; break;
476: }
477: cout << "#$" << hex << ea.addr << dec;
478: break;
479: case imm3:
480: ea.addr = a.reg; ea.type = EAIM;
481: cout << "#$" << hex << ea.addr << dec;
482: break;
483: default:
484: abort(); // FIXME
485: }
486: return ea;
487: }
488:
489: static inline void setflags_add(const ULONG src, const ULONG oldv,
490: const ULONG newv)
491: {
492: int s = src >> 31;
493: int o = oldv >> 31;
494: int n = newv >> 31;
495:
496: regs.z = newv == 0;
497: regs.c = regs.x = (s && o) || (!n && (o || s));
498: regs.n = n;
499: regs.v = ((s && o && !n) || (!s && !o && n));
500: }
501:
502: static inline void setflags_sub(const ULONG src, const ULONG oldv,
503: const ULONG newv)
504: {
505: int s = src >> 31;
506: int o = oldv >> 31;
507: int n = newv >> 31;
508:
509: regs.z = newv == 0;
510: regs.c = regs.x = (s && !o) || (n && (!o || s));
511: regs.n = n;
512: regs.v = ((!s && o && !n) || (s && !o && n));
513: }
514:
515: static inline void setflags_cmp(const ULONG src, const ULONG oldv,
516: const ULONG newv)
517: {
518: int sh = 31; //mask2shift(mask);
519: int s = (src >> sh); // & 1;
520: int o = (oldv >> sh); // & 1;
521: int n = newv >> sh;
522:
523: regs.z = newv == 0;
524: regs.c = (s && !o) || (n && (!o || s));
525: regs.n = n;
526: regs.v = ((!s && o && !n) || (s && !o && n));
527: }
528:
529: static inline void setflags_logical(ULONG newv, const ULONG mask)
530: {
531: newv &= mask;
532: regs.z = newv == 0;
533: regs.n = newv >> mask2shift(mask);
534: regs.v = regs.c = 0;
535: }
536:
537: static bool cctrue(const int cc)
538: {
539: switch(cc){
540: case 0: return true; // T
541: case 1: return false; // F
542: case 2: return !regs.c && !regs.z; // HI
543: case 3: return regs.c || regs.z; // LS
544: case 4: return !regs.c; // CC
545: case 5: return regs.c; // CS
546: case 6: return !regs.z; // NE
547: case 7: return regs.z; // EQ
548: case 8: return !regs.v; // VC
549: case 9: return regs.v; // VV
550: case 10:return !regs.n; // PL
551: case 11:return regs.n; // MI
552: case 12:return regs.n == regs.v; // GE
553: case 13:return regs.n != regs.v; // LT
554: case 14:return !regs.z && (regs.n == regs.v);// GT
555: case 15:return regs.z || (regs.n != regs.v); // LE
556: }
557: abort();
558: return 0;
559: }
560:
561: static void SuperState()
562: {
563: if (!regs.s){
564: regs.s = 1;
565: regs.t = 0;
566: CPTR temp = regs.usp;
567: regs.usp = regs.a[7];
568: regs.a[7] = temp;
569: }
570: }
571:
572: static void UserState()
573: {
574: if (regs.s){
575: regs.s = 0;
576: // regs.t = 0;
577: CPTR temp = regs.usp;
578: regs.usp = regs.a[7];
579: regs.a[7] = temp;
580: }
581: }
582:
583: static void MakeSR()
584: {
585: regs.sr = (regs.t << 15) | (regs.s << 13) | (regs.intmask << 8)
586: | (regs.x << 4) | (regs.n << 3) | (regs.z << 2) | (regs.v << 1)
587: | regs.c;
588: }
589:
590: static void MakeFromSR()
591: {
592: int olds = regs.s;
593:
594: regs.t = (regs.sr >> 15) & 1;
595: regs.s = (regs.sr >> 13) & 1;
596: regs.intmask = (regs.sr >> 8) & 7;
597: regs.x = (regs.sr >> 4) & 1;
598: regs.n = (regs.sr >> 3) & 1;
599: regs.z = (regs.sr >> 2) & 1;
600: regs.v = (regs.sr >> 1) & 1;
601: regs.c = regs.sr & 1;
602: if (olds != regs.s) {
603: cout << "Mode switch!\n";
604: regs.s = olds;
605: if (regs.s) UserState(); else SuperState();
606: }
607: }
608:
609: static void Exception(int nr, int newimask=-1)
610: {
611: MakeSR();
612: SuperState();
613: if (newimask != -1) regs.intmask = newimask;
614: addr_mode pda7(Apdi,7);
615: effadr lea = GetEA(pda7,0xffffffff);
616: effadr wea = GetEA(pda7,0xffff);
617: StoreToEA(wea,regs.sr);
618: StoreToEA(lea,regs.pc);
619: regs.pc = (mem.get_word(4*nr) << 16) + mem.get_word(4*nr+2);
620: }
621:
622: static void Interrupt(int nr)
623: {
624: assert(nr < 8 && nr >= 0);
625: // regs.intmask = nr;
626: Exception(nr+24,nr);
627: }
628:
629: /*
630: * instruction emulations
631: */
632:
633: static instr_result INST_ILLG(const instr_params &)
634: {
635: regs.pc -= 2;
636:
637: Exception(4);
638: }
639:
640: static instr_result INST_NIMP(const instr_params &p)
641: {
642: cout << "unimplemented (020 ??) instruction: "
643: << mem.get_word(regs.pc-2) << "\n";
644: INST_ILLG(p);
645: }
646:
647: static instr_result INST_OR(const instr_params &p)
648: {
649: effadr src = GetEA(p.src, p.mask);
650: ULONG srcv = GetFromEA(src);
651: effadr dst = GetEA(p.dest, p.mask);
652: ULONG dstv = GetFromEA(dst);
653: dstv |= srcv;
654: setflags_logical(dstv, p.mask);
655: StoreToEA(dst,dstv);
656: }
657:
658: static instr_result INST_AND(const instr_params &p)
659: {
660: effadr src = GetEA(p.src, p.mask);
661: ULONG srcv = GetFromEA(src);
662: effadr dst = GetEA(p.dest, p.mask);
663: ULONG dstv = GetFromEA(dst);
664: dstv &= srcv;
665: setflags_logical(dstv, p.mask);
666: StoreToEA(dst,dstv);
667: }
668:
669: static instr_result INST_EOR(const instr_params &p)
670: {
671: effadr src = GetEA(p.src, p.mask);
672: ULONG srcv = GetFromEA(src);
673: effadr dst = GetEA(p.dest, p.mask);
674: ULONG dstv = GetFromEA(dst);
675: dstv ^= srcv;
676: setflags_logical(dstv, p.mask);
677: StoreToEA(dst,dstv);
678: }
679:
680: static instr_result INST_CMP(const instr_params &p)
681: {
682: effadr src = GetEA(p.src, p.mask);
683: ULONG srcv = GetFromEA(src);
684: effadr dst = GetEA(p.dest, p.mask);
685: ULONG dstv = GetFromEA(dst);
686: ULONG newv = dstv - srcv;
687: setflags_cmp(srcv, dstv, newv);
688: }
689:
690: static instr_result INST_ADD(const instr_params &p)
691: {
692: effadr src = GetEA(p.src, p.mask);
693: ULONG srcv = GetFromEA(src);
694: effadr dst = GetEA(p.dest, p.mask);
695: ULONG dstv = GetFromEA(dst);
696: ULONG newv = dstv + srcv;
697: setflags_add(srcv, dstv, newv);
698: StoreToEA(dst,newv);
699: }
700:
701: static instr_result INST_SUB(const instr_params &p)
702: {
703: effadr src = GetEA(p.src, p.mask);
704: ULONG srcv = GetFromEA(src);
705: effadr dst = GetEA(p.dest, p.mask);
706: ULONG dstv = GetFromEA(dst);
707: ULONG newv = dstv - srcv;
708: setflags_sub(srcv, dstv, newv);
709: StoreToEA(dst,newv);
710: }
711:
712: static instr_result INST_ADDX(const instr_params &p)
713: {
714: effadr src = GetEA(p.src, p.mask);
715: ULONG srcv = GetFromEA(src);
716: effadr dst = GetEA(p.dest, p.mask);
717: ULONG dstv = GetFromEA(dst);
718: ULONG newv = dstv + srcv + regs.x;
719: setflags_add(srcv, dstv, newv);
720: StoreToEA(dst,newv);
721: }
722:
723: static instr_result INST_SUBX(const instr_params &p)
724: {
725: effadr src = GetEA(p.src, p.mask);
726: ULONG srcv = GetFromEA(src);
727: effadr dst = GetEA(p.dest, p.mask);
728: ULONG dstv = GetFromEA(dst);
729: ULONG newv = dstv - srcv - regs.x;
730: setflags_sub(srcv, dstv, newv);
731: StoreToEA(dst,newv);
732: }
733:
734: static instr_result INST_ADDA(const instr_params &p)
735: {
736: effadr src = GetEA(p.src, p.mask);
737: ULONG srcv = GetFromEA(src);
738: effadr dst = GetEA(p.dest, 0xffffffff);
739: ULONG dstv = GetFromEA(dst);
740: // if (src.szmask == 0xffff) srcv = ExtendWord(srcv);
741: StoreToEA(dst,dstv + srcv);
742: }
743:
744: static instr_result INST_SUBA(const instr_params &p)
745: {
746: effadr src = GetEA(p.src, p.mask);
747: ULONG srcv = GetFromEA(src);
748: effadr dst = GetEA(p.dest, 0xffffffff);
749: ULONG dstv = GetFromEA(dst);
750: // if (src.szmask == 0xffff) srcv = ExtendWord(srcv);
751: StoreToEA(dst,dstv - srcv);
752: }
753:
754: static instr_result INST_CMPA(const instr_params &p)
755: {
756: effadr src = GetEA(p.src, p.mask);
757: ULONG srcv = GetFromEA(src);
758: effadr dst = GetEA(p.dest, 0xffffffff);
759: ULONG dstv = GetFromEA(dst);
760: ULONG newv = dstv - srcv;
761: setflags_cmp(srcv, dstv, newv);
762: }
763:
764: static instr_result INST_CHK(const instr_params &p)
765: {
766: cout << "CHK occurred\n";
767: INST_ILLG(p); // FIXME
768: }
769:
770: static instr_result INST_EXGL(const instr_params &p)
771: {
772: effadr src = GetEA(p.src, p.mask);
773: ULONG srcv = GetFromEA(src);
774: effadr dst = GetEA(p.dest, p.mask);
775: ULONG dstv = GetFromEA(dst);
776: StoreToEA(dst,srcv);
777: StoreToEA(src,dstv);
778: }
779:
780: static instr_result INST_LEA(const instr_params &p)
781: {
782: effadr src = GetEA(p.src, p.mask);
783: effadr dst = GetEA(p.dest, p.mask);
784: StoreToEA(dst,RetrieveEA(src));
785: }
786:
787: static instr_result INST_MOVE(const instr_params &p)
788: {
789: effadr src = GetEA(p.src, p.mask);
790: ULONG srcv = GetFromEA(src);
791: effadr dst = GetEA(p.dest, p.mask);
792: setflags_logical(srcv,p.mask);
793: StoreToEA(dst,srcv);
794: }
795:
796: static instr_result INST_MOVEQ(const instr_params &p)
797: {
798: effadr src = GetEA(p.src, p.mask);
799: effadr dst = GetEA(p.dest, p.mask);
800: ULONG srcv = ExtendByte(GetFromEA(src));
801: setflags_logical(srcv,p.mask);
802: StoreToEA(dst,srcv);
803: }
804:
805: static instr_result INST_MOVEA(const instr_params &p)
806: {
807: effadr src = GetEA(p.src, p.mask);
808: ULONG srcv = GetFromEA(src);
809: effadr dst = GetEA(p.dest, p.mask);
810: StoreToEA(dst,srcv);
811: }
812:
813: static instr_result INST_BTST(const instr_params &p)
814: {
815: effadr src = GetEA(p.src, p.mask);
816: ULONG srcv = GetFromEA(src);
817: effadr dst = GetEA(p.dest, p.dest.mode == Dreg ? 0xffffffff : 0xff);
818: ULONG dstv = GetFromEA(dst);
819: if (p.dest.mode == Dreg) {
820: srcv &= 31;
821: } else {
822: srcv &= 7;
823: }
824: regs.z = !(dstv & (1 << srcv));
825: }
826:
827: static instr_result INST_BCLR(const instr_params &p)
828: {
829: effadr src = GetEA(p.src, p.mask);
830: ULONG srcv = GetFromEA(src);
831: effadr dst = GetEA(p.dest, p.dest.mode == Dreg ? 0xffffffff : 0xff);
832: ULONG dstv = GetFromEA(dst);
833: if (p.dest.mode == Dreg) {
834: srcv &= 31;
835: } else {
836: srcv &= 7;
837: }
838: regs.z = !(dstv & (1 << srcv));
839: StoreToEA(dst,dstv & ~(1 << srcv));
840: }
841:
842: static instr_result INST_BSET(const instr_params &p)
843: {
844: effadr src = GetEA(p.src, p.mask);
845: ULONG srcv = GetFromEA(src);
846: effadr dst = GetEA(p.dest, p.dest.mode == Dreg ? 0xffffffff : 0xff);
847: ULONG dstv = GetFromEA(dst);
848: if (p.dest.mode == Dreg) {
849: srcv &= 31;
850: } else {
851: srcv &= 7;
852: }
853: regs.z = !(dstv & (1 << srcv));
854: StoreToEA(dst,dstv | (1 << srcv));
855: }
856:
857: static instr_result INST_BCHG(const instr_params &p)
858: {
859: effadr src = GetEA(p.src, p.mask);
860: ULONG srcv = GetFromEA(src);
861: effadr dst = GetEA(p.dest, p.dest.mode == Dreg ? 0xffffffff : 0xff);
862: ULONG dstv = GetFromEA(dst);
863: if (p.dest.mode == Dreg) {
864: srcv &= 31;
865: } else {
866: srcv &= 7;
867: }
868: regs.z = !(dstv & (1 << srcv));
869: StoreToEA(dst,dstv ^ (1 << srcv));
870: }
871:
872: static instr_result INST_NEG(const instr_params &p)
873: {
874: effadr ea = GetEA(p.src, p.mask);
875: ULONG val = GetFromEA(ea);
876: ULONG newv = -val;
877: setflags_sub(val, 0, newv);
878: StoreToEA(ea,newv);
879: }
880:
881: static instr_result INST_NEGX(const instr_params &p)
882: {
883: effadr ea = GetEA(p.src, p.mask);
884: ULONG val = GetFromEA(ea);
885: ULONG newv = -val-regs.x;
886: setflags_sub(val, 0, newv);
887: StoreToEA(ea,newv);
888: }
889:
890: static instr_result INST_NOT(const instr_params &p)
891: {
892: effadr ea = GetEA(p.src, p.mask);
893: ULONG val = GetFromEA(ea);
894: ULONG newv = ~val;
895: setflags_logical(newv,p.mask);
896: StoreToEA(ea,newv);
897: }
898:
899: static instr_result INST_CLR(const instr_params &p)
900: {
901: effadr ea = GetEA(p.src, p.mask);
902: ULONG val = GetFromEA(ea); // not a bug, a feature!
903: ULONG newv = 0;
904: setflags_logical(newv,p.mask);
905: StoreToEA(ea,newv);
906: }
907:
908: static instr_result INST_TST(const instr_params &p)
909: {
910: effadr ea = GetEA(p.src, p.mask);
911: ULONG val = GetFromEA(ea);
912: setflags_logical(val,p.mask);
913: }
914:
915: static instr_result INST_SWAP(const instr_params &p)
916: {
917: effadr ea = GetEA(p.src, p.mask);
918: ULONG val = GetFromEA(ea);
919: val = (val >> 16) | (val << 16);
920: StoreToEA(ea, val);
921: setflags_logical(val,p.mask);
922: }
923:
924: static instr_result INST_EXTW(const instr_params &p)
925: {
926: effadr ea = GetEA(p.src, p.mask);
927: ULONG val = GetFromEA(ea);
928: StoreToEA(ea, ExtendByte(val));
929: }
930:
931: static instr_result INST_EXTL(const instr_params &p)
932: {
933: effadr ea = GetEA(p.src, p.mask);
934: ULONG val = GetFromEA(ea);
935: StoreToEA(ea, ExtendWord(val));
936: }
937:
938: static instr_result INST_Scc(const instr_params &p)
939: {
940: effadr ea = GetEA(p.src, p.mask);
941: StoreToEA(ea,cctrue(p.dest.reg) ? 0xff : 0);
942: }
943:
944: static instr_result INST_ABCD(const instr_params &p)
945: {
946: abort(); // FIXME
947: }
948:
949: static instr_result INST_SBCD(const instr_params &p)
950: {
951: abort(); // FIXME
952: }
953:
954: static instr_result INST_NBCD(const instr_params &p)
955: {
956: abort(); // FIXME
957: }
958:
959: static instr_result INST_NOP(const instr_params &)
960: {
961: // :-D
962: }
963:
964: static instr_result INST_RESET(const instr_params &)
965: {
966: customreset();
967: }
968:
969: static instr_result INST_STOP(const instr_params &p)
970: {
971: if ((p.mask != 0xff) && !regs.s) {
972: regs.pc -= 2;
973: Exception(8);
974: } else {
975: effadr ea = GetEA(p.src, p.mask);
976: regs.sr = GetFromEA(ea);
977: MakeFromSR();
978: regs.stopped = 1;
979: }
980: }
981:
982: static instr_result INST_TRAPV(const instr_params &)
983: {
984: if (regs.v) Exception(7);
985: }
986:
987: static instr_result INST_TRAP(const instr_params &p)
988: {
989: UWORD val = GetFromEA(GetEA(p.src,p.mask));
990: Exception(val+32);
991: }
992:
993: static instr_result INST_BSRB(const instr_params &p)
994: {
995: effadr ea = GetEA(p.src, p.mask);
996: BYTE offset = GetFromEA(ea);
997: addr_mode pda7(Apdi,7);
998: effadr stackp = GetEA(pda7,0xffffffff);
999: StoreToEA(stackp,regs.pc);
1000: regs.pc += offset;
1001: }
1002:
1003: static instr_result INST_BccB(const instr_params &p)
1004: {
1005: if (cctrue(p.dest.reg)){
1006: effadr ea = GetEA(p.src, p.mask);
1007: BYTE offset = GetFromEA(ea);
1008: regs.pc += offset;
1009: }
1010: }
1011:
1012: static instr_result INST_BSRW(const instr_params &p)
1013: {
1014: effadr ea = GetEA(p.src, p.mask);
1015: WORD offset = GetFromEA(ea);
1016: addr_mode pda7(Apdi,7);
1017: effadr stackp = GetEA(pda7,0xffffffff);
1018: StoreToEA(stackp,regs.pc);
1019: regs.pc += offset - 2;
1020: }
1021:
1022: static instr_result INST_BccW(const instr_params &p)
1023: {
1024: effadr ea = GetEA(p.src, p.mask);
1025: WORD offset = GetFromEA(ea);
1026: if (cctrue(p.dest.reg)){
1027: regs.pc += offset - 2;
1028: }
1029: }
1030:
1031: static instr_result INST_DBcc(const instr_params &p)
1032: {
1033: WORD offset = nextiword();
1034:
1035: if (!cctrue(p.dest.reg)){
1036: effadr ea = GetEA(p.src, p.mask); // safe inside if, can only be Dreg
1037: ULONG dr = GetFromEA(ea);
1038: if (dr--){
1039: regs.pc += offset - 2;
1040: }
1041: StoreToEA(ea,dr);
1042: }
1043: }
1044:
1045: static instr_result INST_JMP(const instr_params &p)
1046: {
1047: effadr ea = GetEA(p.src, p.mask);
1048: regs.pc = RetrieveEA(ea);
1049: }
1050:
1051: static instr_result INST_JSR(const instr_params &p)
1052: {
1053: effadr ea = GetEA(p.src, p.mask);
1054:
1055: addr_mode pda7(Apdi,7);
1056: effadr stackp = GetEA(pda7,0xffffffff);
1057: StoreToEA(stackp, regs.pc);
1058:
1059: regs.pc = RetrieveEA(ea);
1060: }
1061:
1062: static instr_result INST_RTE(const instr_params &)
1063: {
1064: addr_mode a7pi(Aipi,7);
1065: effadr stackp = GetEA(a7pi,0xffff);
1066: regs.sr = GetFromEA(stackp);
1067: stackp = GetEA(a7pi,0xffffffff);
1068: regs.pc = GetFromEA(stackp);
1069: MakeFromSR();
1070: }
1071:
1072: static instr_result INST_RTD(const instr_params &p)
1073: {
1074: INST_NIMP(p); // FIXME
1075: }
1076:
1077: static instr_result INST_RTS(const instr_params &)
1078: {
1079: addr_mode a7pi(Aipi,7);
1080: effadr stackp = GetEA(a7pi,0xffffffff);
1081: regs.pc = GetFromEA(stackp);
1082: }
1083:
1084: static instr_result INST_RTR(const instr_params &)
1085: {
1086: MakeSR();
1087: regs.sr &= 0xff00;
1088: addr_mode a7pi(Aipi,7);
1089: effadr stackp = GetEA(a7pi,0xffff);
1090: regs.sr |= GetFromEA(stackp) & 0xff;
1091: stackp = GetEA(a7pi,0xffffffff);
1092: regs.pc = GetFromEA(stackp);
1093: MakeFromSR();
1094: }
1095:
1096: static instr_result INST_LINK(const instr_params &p)
1097: {
1098: addr_mode pda7(Apdi,7);
1099: effadr stackp = GetEA(pda7,0xffffffff);
1100: effadr ar = GetEA(p.src, 0xffffffff);
1101: StoreToEA(stackp, GetFromEA(ar));
1102: StoreToEA(ar, regs.a[7]);
1103: effadr ea = GetEA(p.dest, p.mask);
1104: ULONG offset = GetFromEA(ea);
1105: // if (p.mask = 0xffff) offset = ExtendWord(offset);
1106: regs.a[7] += offset;
1107: }
1108:
1109: static instr_result INST_UNLK(const instr_params &p)
1110: {
1111: effadr ar = GetEA(p.src, 0xffffffff);
1112: regs.a[7] = GetFromEA(ar);
1113:
1114: addr_mode a7pi(Aipi,7);
1115: effadr stackp = GetEA(a7pi,0xffffffff);
1116: StoreToEA(ar, GetFromEA(stackp));
1117: }
1118:
1119: static instr_result INST_MULU(const instr_params &p)
1120: {
1121: effadr src = GetEA(p.src, p.mask);
1122: UWORD srcv = GetFromEA(src);
1123: effadr dst = GetEA(p.dest, p.mask);
1124: UWORD dstv = GetFromEA(dst);
1125: ULONG newv = (ULONG)dstv * (ULONG)srcv;
1126: setflags_logical(newv, 0xffffffff);
1127: dst.szmask = 0xffffffff;
1128: StoreToEA(dst,newv);
1129: }
1130:
1131: static instr_result INST_MULS(const instr_params &p)
1132: {
1133: effadr src = GetEA(p.src, p.mask);
1134: WORD srcv = GetFromEA(src);
1135: effadr dst = GetEA(p.dest, p.mask);
1136: WORD dstv = GetFromEA(dst);
1137: ULONG newv = (LONG)dstv * (LONG)srcv;
1138: setflags_logical(newv, 0xffffffff);
1139: dst.szmask = 0xffffffff;
1140: StoreToEA(dst,newv);
1141: }
1142:
1143: static instr_result INST_DIVU(const instr_params &p)
1144: {
1145: effadr src = GetEA(p.src, 0xffff);
1146: UWORD srcv = GetFromEA(src);
1147: effadr dst = GetEA(p.dest, 0xffffffff);
1148: ULONG dstv = GetFromEA(dst);
1149: if (srcv == 0){
1150: // FOO !
1151: } else {
1152: ULONG newv = dstv / srcv;
1153: UWORD rem = dstv % srcv;
1154: setflags_logical(newv, 0xffff);
1155: regs.v = newv > 0xffff;
1156: newv = (newv & 0xffff) | (rem << 16);
1157: StoreToEA(dst,newv);
1158: }
1159: }
1160:
1161: static instr_result INST_DIVS(const instr_params &p)
1162: {
1163: effadr src = GetEA(p.src, 0xffff);
1164: WORD srcv = GetFromEA(src);
1165: effadr dst = GetEA(p.dest, 0xffffffff);
1166: LONG dstv = GetFromEA(dst);
1167: if (srcv == 0){
1168: // FOO !
1169: } else {
1170: LONG newv = dstv / srcv;
1171: UWORD rem = dstv % srcv;
1172: if ((rem & 0x8000) != (newv & 0x8000)) rem = -rem;
1173: setflags_logical(newv, 0xffff);
1174: regs.v = (newv & 0xffff0000) && (newv & 0xffff0000) != 0xffff0000;
1175: newv = (newv & 0xffff) | (rem << 16);
1176: StoreToEA(dst,newv);
1177: }
1178: }
1179:
1180: static instr_result INST_ASL(const instr_params &p)
1181: {
1182: effadr src = GetEA(p.src, p.mask);
1183: effadr dst = GetEA(p.dest, p.mask);
1184: ULONG cnt = GetFromEA(src) & 31;
1185: ULONG data = GetFromEA(dst) & p.mask;
1186:
1187: ULONG cmask = 1 << mask2shift(p.mask);
1188: ULONG sign = data & cmask;
1189: regs.v = 0;
1190: for (;cnt;--cnt){
1191: regs.c = regs.x = (data & cmask) != 0;
1192: data <<= 1;
1193: if ((data & cmask) != sign) regs.v = 1;
1194: }
1195: regs.n = (data & cmask) != 0;
1196: regs.z = (data & p.mask) == 0;
1197: StoreToEA(dst,data);
1198: }
1199:
1200: static instr_result INST_ASR(const instr_params &p)
1201: {
1202: effadr src = GetEA(p.src, p.mask);
1203: effadr dst = GetEA(p.dest, p.mask);
1204: ULONG cnt = GetFromEA(src) & 31;
1205: ULONG data = GetFromEA(dst) & p.mask;
1206:
1207: ULONG cmask = 1 << mask2shift(p.mask);
1208: ULONG sign = data & cmask;
1209: regs.v = 0;
1210: for (;cnt;--cnt){
1211: regs.c = regs.x = data & 1;
1212: data = (data >> 1) | sign;
1213: }
1214: regs.n = sign != 0;
1215: regs.z = (data & p.mask) == 0;
1216: StoreToEA(dst,data);
1217: }
1218:
1219: static instr_result INST_LSR(const instr_params &p)
1220: {
1221: effadr src = GetEA(p.src, p.mask);
1222: effadr dst = GetEA(p.dest, p.mask);
1223: ULONG cnt = GetFromEA(src) & 31;
1224: ULONG data = GetFromEA(dst) & p.mask;
1225:
1226: int carry = 0;
1227: for (;cnt;--cnt){
1228: carry = data & 1;
1229: data >>= 1;
1230: }
1231: setflags_logical(data,p.mask);
1232: regs.c = regs.x = carry;
1233: StoreToEA(dst,data);
1234: }
1235:
1236: static instr_result INST_LSL(const instr_params &p)
1237: {
1238: effadr src = GetEA(p.src, p.mask);
1239: effadr dst = GetEA(p.dest, p.mask);
1240: ULONG cnt = GetFromEA(src) & 31;
1241: ULONG data = GetFromEA(dst) & p.mask;
1242:
1243: ULONG cmask = 1 << mask2shift(p.mask);
1244: ULONG carry = 0;
1245:
1246: for (;cnt;--cnt){
1247: carry = data & cmask;
1248: data <<= 1;
1249: }
1250: setflags_logical(data,p.mask);
1251: regs.c = regs.x = carry != 0;
1252: StoreToEA(dst,data);
1253: }
1254:
1255: static instr_result INST_ROR(const instr_params &p)
1256: {
1257: effadr src = GetEA(p.src, p.mask);
1258: effadr dst = GetEA(p.dest, p.mask);
1259: ULONG cnt = GetFromEA(src) & 31;
1260: ULONG data = GetFromEA(dst) & p.mask;
1261:
1262: ULONG cmask = 1 << mask2shift(p.mask);
1263: int carry = 0;
1264: for (;cnt;--cnt){
1265: carry = data & 1;
1266: data >>= 1;
1267: if (carry) data |= cmask;
1268: }
1269: setflags_logical(data,p.mask);
1270: regs.c = carry;
1271: StoreToEA(dst,data);
1272: }
1273:
1274: static instr_result INST_ROL(const instr_params &p)
1275: {
1276: effadr src = GetEA(p.src, p.mask);
1277: effadr dst = GetEA(p.dest, p.mask);
1278: ULONG cnt = GetFromEA(src) & 31;
1279: ULONG data = GetFromEA(dst) & p.mask;
1280:
1281: ULONG cmask = 1 << mask2shift(p.mask);
1282: ULONG carry = 0;
1283:
1284: for (;cnt;--cnt){
1285: carry = data & cmask;
1286: data <<= 1;
1287: if (carry) data |= 1;
1288: }
1289: setflags_logical(data,p.mask);
1290: regs.c = carry != 0;
1291: StoreToEA(dst,data);
1292: }
1293:
1294: static instr_result INST_ROXR(const instr_params &p)
1295: {
1296: effadr src = GetEA(p.src, p.mask);
1297: effadr dst = GetEA(p.dest, p.mask);
1298: ULONG cnt = GetFromEA(src) & 31;
1299: ULONG data = GetFromEA(dst) & p.mask;
1300:
1301: ULONG cmask = 1 << mask2shift(p.mask);
1302: int carry = 0;
1303: for (;cnt;--cnt){
1304: carry = data & 1;
1305: data >>= 1;
1306: if (regs.x) data |= cmask;
1307: regs.x = carry;
1308: }
1309: setflags_logical(data,p.mask);
1310: regs.c = regs.x = carry;
1311: StoreToEA(dst,data);
1312: }
1313:
1314: static instr_result INST_ROXL(const instr_params &p)
1315: {
1316: effadr src = GetEA(p.src, p.mask);
1317: effadr dst = GetEA(p.dest, p.mask);
1318: ULONG cnt = GetFromEA(src) & 31;
1319: ULONG data = GetFromEA(dst) & p.mask;
1320:
1321: ULONG cmask = 1 << mask2shift(p.mask);
1322: int carry = 0;
1323:
1324: for (;cnt;--cnt){
1325: carry = data & cmask;
1326: data <<= 1;
1327: if (regs.x) data |= 1;
1328: regs.x = carry != 0;
1329: }
1330: setflags_logical(data,p.mask);
1331: regs.c = regs.x = carry != 0;
1332: StoreToEA(dst,data);
1333: }
1334:
1335: static instr_result INST_ASL1(const instr_params &p)
1336: {
1337: effadr dst = GetEA(p.dest, p.mask);
1338: ULONG data = GetFromEA(dst) & p.mask;
1339:
1340: ULONG cmask = 1 << mask2shift(p.mask);
1341: ULONG sign = data & cmask;
1342: regs.v = 0;
1343: regs.c = regs.x = sign != 0;
1344: data <<= 1;
1345: if ((data & cmask) != sign) regs.v = 1;
1346: regs.n = (data & cmask) != 0;
1347: regs.z = (data & p.mask) == 0;
1348: StoreToEA(dst,data);
1349: }
1350:
1351: static instr_result INST_ASR1(const instr_params &p)
1352: {
1353: effadr dst = GetEA(p.dest, p.mask);
1354: ULONG data = GetFromEA(dst) & p.mask;
1355:
1356: ULONG cmask = 1 << mask2shift(p.mask);
1357: ULONG sign = data & cmask;
1358: regs.v = 0;
1359: regs.c = regs.x = data & 1;
1360: data = (data >> 1) | sign;
1361: regs.n = sign != 0;
1362: regs.z = (data & p.mask) == 0;
1363: StoreToEA(dst,data);
1364: }
1365:
1366: static instr_result INST_LSR1(const instr_params &p)
1367: {
1368: effadr dst = GetEA(p.dest, p.mask);
1369: ULONG data = GetFromEA(dst) & p.mask;
1370: int carry = data & 1;
1371: data >>= 1;
1372: setflags_logical(data, p.mask);
1373: regs.c = regs.x = carry;
1374: StoreToEA(dst,data);
1375: }
1376:
1377: static instr_result INST_LSL1(const instr_params &p)
1378: {
1379: effadr dst = GetEA(p.dest, p.mask);
1380: ULONG data = GetFromEA(dst) & p.mask;
1381:
1382: ULONG cmask = 1 << mask2shift(p.mask);
1383: ULONG carry = data & cmask;
1384: data <<= 1;
1385: setflags_logical(data,p.mask);
1386: regs.c = regs.x = carry != 0;
1387: StoreToEA(dst,data);
1388: }
1389:
1390: static instr_result INST_ROR1(const instr_params &p)
1391: {
1392: effadr dst = GetEA(p.dest, p.mask);
1393: ULONG data = GetFromEA(dst) & p.mask;
1394:
1395: ULONG cmask = 1 << mask2shift(p.mask);
1396: int carry = data & 1;
1397: data >>= 1;
1398: if (carry) data |= cmask;
1399: setflags_logical(data,p.mask);
1400: regs.c = carry;
1401: StoreToEA(dst,data);
1402: }
1403:
1404: static instr_result INST_ROL1(const instr_params &p)
1405: {
1406: effadr dst = GetEA(p.dest, p.mask);
1407: ULONG data = GetFromEA(dst) & p.mask;
1408:
1409: ULONG cmask = 1 << mask2shift(p.mask);
1410: ULONG carry = data & cmask;
1411:
1412: data <<= 1;
1413: if (carry) data |= 1;
1414: setflags_logical(data,p.mask);
1415: regs.c = carry != 0;
1416: StoreToEA(dst,data);
1417: }
1418:
1419: static instr_result INST_ROXR1(const instr_params &p)
1420: {
1421: effadr dst = GetEA(p.dest, p.mask);
1422: ULONG data = GetFromEA(dst) & p.mask;
1423:
1424: ULONG cmask = 1 << mask2shift(p.mask);
1425: int carry = data & 1;
1426: data >>= 1;
1427: if (regs.x) data |= cmask;
1428: // regs.x = carry;
1429: setflags_logical(data,p.mask);
1430: regs.c = regs.x = carry;
1431: StoreToEA(dst,data);
1432: }
1433:
1434: static instr_result INST_ROXL1(const instr_params &p)
1435: {
1436: effadr dst = GetEA(p.dest, p.mask);
1437: ULONG data = GetFromEA(dst) & p.mask;
1438:
1439: ULONG cmask = 1 << mask2shift(p.mask);
1440: ULONG carry = data & cmask;
1441:
1442: data <<= 1;
1443: if (regs.x) data |= 1;
1444: // regs.x = carry != 0;
1445:
1446: setflags_logical(data,p.mask);
1447: regs.c = regs.x = carry != 0;
1448: StoreToEA(dst,data);
1449: }
1450:
1451: static instr_result INST_MOVECCREA(const instr_params &p)
1452: {
1453: INST_NIMP(p); // FIXME
1454: }
1455:
1456: static instr_result INST_MOVESREA(const instr_params &p)
1457: {
1458: effadr ea = GetEA(p.src, p.mask);
1459: MakeSR();
1460: StoreToEA(ea,regs.sr);
1461: }
1462:
1463: static instr_result INST_MOVEEACCR(const instr_params &p)
1464: {
1465: MakeSR();
1466: regs.sr &= 0xFF00;
1467: effadr ea = GetEA(p.src, p.mask);
1468: regs.sr |= GetFromEA(ea) & 0xFF;
1469: MakeFromSR();
1470: }
1471:
1472: static instr_result INST_MOVEEASR(const instr_params &p)
1473: {
1474: if ((p.mask != 0xff) && !regs.s) {
1475: regs.pc -= 2;
1476: Exception(8);
1477: } else {
1478: effadr ea = GetEA(p.src, p.mask);
1479: regs.sr = GetFromEA(ea);
1480: MakeFromSR();
1481: }
1482: }
1483:
1484: static instr_result INST_ORSR(const instr_params &p)
1485: {
1486: if ((p.mask != 0xff) && !regs.s) {
1487: regs.pc -= 2;
1488: Exception(8);
1489: } else {
1490: MakeSR();
1491: effadr ea = GetEA(p.src, p.mask);
1492: regs.sr |= GetFromEA(ea);
1493: MakeFromSR();
1494: }
1495: }
1496:
1497: static instr_result INST_EORSR(const instr_params &p)
1498: {
1499: if ((p.mask != 0xff) && !regs.s) {
1500: regs.pc -= 2;
1501: Exception(8);
1502: } else {
1503: MakeSR();
1504: effadr ea = GetEA(p.src, p.mask);
1505: regs.sr ^= GetFromEA(ea);
1506: MakeFromSR();
1507: }
1508: }
1509:
1510: static instr_result INST_ANDSR(const instr_params &p)
1511: {
1512: if ((p.mask != 0xff) && !regs.s) {
1513: regs.pc -= 2;
1514: Exception(8);
1515: } else {
1516: MakeSR();
1517: effadr ea = GetEA(p.src, p.mask);
1518: regs.sr &= GetFromEA(ea);
1519: MakeFromSR();
1520: }
1521: }
1522:
1523: static instr_result INST_MOVEMEARL(const instr_params &p)
1524: {
1525: int i;
1526: UWORD bitmask = nextiword();
1527: effadr ea = MGetEA(p.src, p.mask);
1528: for(i=0; i<8; i++) {
1529: if (bitmask & (1 << i)) {
1530: regs.d[i] = (regs.d[i] & ~p.mask) | (GetFromEA(ea) & p.mask);
1531: ea.addr += mask2len(p.mask);
1532: }
1533: }
1534: for(i=0; i<8; i++) {
1535: if (bitmask & (1 << (i + 8))) {
1536: regs.a[i] = Extend(GetFromEA(ea),p.mask);
1537: ea.addr += mask2len(p.mask);
1538: }
1539: }
1540: MCompleteEAToRL(ea, p.src, p.mask, bitmask);
1541: }
1542:
1543: static instr_result INST_MOVEMRLEA(const instr_params &p)
1544: {
1545: int rd[8], ra[8], i, kludge;
1546: for(i=0;i<8;i++){
1547: rd[i] = regs.d[i]; ra[i] = regs.a[i];
1548: }
1549: UWORD bitmask = nextiword();
1550: effadr ea = MGetEA(p.src, p.mask);
1551: kludge = (p.src.mode == Apdi) ? 15 : 0;
1552: MCompleteEAFromRL(ea, p.src, p.mask, bitmask);
1553: for(i=0; i<8; i++) {
1554: if (bitmask & (1 << (i ^ kludge))) {
1555: StoreToEA(ea,rd[i]);
1556: ea.addr += mask2len(p.mask);
1557: }
1558: }
1559: for(i=0; i<8; i++) {
1560: if (bitmask & (1 << ((i + 8) ^ kludge))) {
1561: StoreToEA(ea,ra[i]);
1562: ea.addr += mask2len(p.mask);
1563: }
1564: }
1565: }
1566:
1567: static instr_result INST_MOVEAUSP(const instr_params &p)
1568: {
1569: effadr ea = GetEA(p.src,0xffffffff);
1570: if (regs.s) {
1571: regs.usp = GetFromEA(ea);
1572: } else {
1573: regs.pc -= 2; Exception(8);
1574: }
1575: }
1576:
1577: static instr_result INST_MOVEUSPA(const instr_params &p)
1578: {
1579: effadr ea = GetEA(p.src,0xffffffff);
1580: if (regs.s) {
1581: StoreToEA(ea,regs.usp);
1582: } else {
1583: regs.pc -= 2; Exception(8);
1584: }
1585: }
1586:
1587: static instr_result INST_LINEA(const instr_params &)
1588: {
1589: regs.pc -= 2;
1590:
1591: Exception(10);
1592: }
1593:
1594: static instr_result INST_LINEF(const instr_params &)
1595: {
1596: regs.pc -= 2;
1597:
1598: Exception(11);
1599: }
1600:
1601: /*
1602: * debugging functions
1603: */
1604:
1605: struct debug_entry {
1606: instr_func f;
1607: char *name;
1608: bool src,dest,spc;
1609: };
1610:
1611: static debug_entry debugtbl[] = {
1612: { &INST_OR,"OR",1,1,0 },
1613: { &INST_AND,"AND",1,1,0 },
1614: { &INST_EOR,"EOR",1,1,0 },
1615: { &INST_CMP,"CMP",1,1,0 },
1616: { &INST_ADD,"ADD",1,1,0 },
1617: { &INST_SUB,"SUB",1,1,0 },
1618: { &INST_ADDX,"ADDX",1,1,0 },
1619: { &INST_SUBX,"SUBX",1,1,0 },
1620:
1621: { &INST_ADDA,"ADDA",1,1,0 },
1622: { &INST_SUBA,"SUBA",1,1,0 },
1623: { &INST_CMPA,"CMPA",1,1,0 },
1624:
1625: { &INST_CHK,"CHK",1,1,0 },
1626:
1627: { &INST_EXGL,"EXG",1,1,0 },
1628:
1629: { &INST_LEA,"LEA",1,1,0 },
1630: { &INST_MOVE,"MOVE",1,1,0 },
1631: { &INST_MOVEA,"MOVEA",1,1,0 },
1632: { &INST_MOVEQ,"MOVEQ",1,1,0 },
1633: { &INST_BTST,"BTST",1,1,0 },
1634: { &INST_BCLR,"BCLR",1,1,0 },
1635: { &INST_BSET,"BSET",1,1,0 },
1636: { &INST_BCHG,"BCHG",1,1,0 },
1637: { &INST_NEG,"NEG",1,0,0 },
1638: { &INST_NEGX,"NEGX",1,0,0 },
1639: { &INST_NOT,"NOT",1,0,0 },
1640: { &INST_CLR,"CLR",1,0,0 },
1641: { &INST_TST,"TST",1,0,0 },
1642: { &INST_SWAP,"SWAP",1,0,0 },
1643: { &INST_EXTW,"EXT",1,0,0 },
1644: { &INST_EXTL,"EXT",1,0,0 },
1645: { &INST_Scc,"Scc",1,0,0 },
1646: { &INST_ABCD,"ABCD",1,1,0 },
1647: { &INST_SBCD,"SBCD",1,1,0 },
1648: { &INST_NBCD,"NBCD",1,1,0 },
1649: { &INST_NOP,"NOP",0,0,0 },
1650: { &INST_RESET,"RESET",0,0,0 },
1651: { &INST_STOP,"STOP",1,0,0 },
1652: { &INST_TRAPV,"TRAPV",1,0,0 },
1653: { &INST_TRAP,"TRAP",1,0,0 },
1654: { &INST_BSRB,"BSR",1,0,0 },
1655: { &INST_BccB,"Bcc",1,0,0 },
1656: { &INST_BSRW,"BSR",1,0,0 },
1657: { &INST_BccW,"Bcc",1,0,0 },
1658: { &INST_DBcc,"DBcc",1,0,10 },
1659: { &INST_JMP,"JMP",1,0,0 },
1660: { &INST_JSR,"JSR",1,0,0 },
1661: { &INST_RTE,"RTE",0,0,0 },
1662: { &INST_RTD,"RTD",0,0,0 },
1663: { &INST_RTS,"RTS",0,0,0 },
1664: { &INST_RTR,"RTR",0,0,0 },
1665: { &INST_LINK,"LINK",1,1,0 },
1666: { &INST_UNLK,"UNLK",1,0,0 },
1667: { &INST_MULU,"MULU",1,1,0 },
1668: { &INST_MULS,"MULS",1,1,0 },
1669: { &INST_DIVU, "DIVU",1,1,0 },
1670: { &INST_DIVS,"DIVS",1,1,0 },
1671: { &INST_ASR,"ASR",1,1,0 },
1672: { &INST_ASL,"ASL",1,1,0 },
1673: { &INST_LSR,"LSR",1,1,0 },
1674: { &INST_LSL,"LSL",1,1,0 },
1675: { &INST_ROR,"ROR",1,1,0 },
1676: { &INST_ROL,"ROL",1,1,0 },
1677: { &INST_ROXR,"ROXR",1,1,0 },
1678: { &INST_ROXL,"ROXL",1,1,0 },
1679: { &INST_ASR1,"ASR",1,0,0 },
1680: { &INST_ASL1,"ASL",1,0,0 },
1681: { &INST_LSR1,"LSR",1,0,0 },
1682: { &INST_LSL1,"LSL",1,0,0 },
1683: { &INST_ROR1,"ROR",1,0,0 },
1684: { &INST_ROL1,"ROL",1,0,0 },
1685: { &INST_ROXR1,"ROXR",1,0,0 },
1686: { &INST_ROXL1,"ROXL",1,0,0 },
1687: { &INST_MOVECCREA,"MOVE CCR,",1,0,0 },
1688: { &INST_MOVESREA,"MOVE SR,",1,0,0 },
1689: { &INST_MOVEEACCR,"MOVE2CCR",1,0,0 },
1690: { &INST_MOVEEASR,"MOVE2SR",1,0,0 },
1691: { &INST_MOVEMEARL,"MOVEM",1,0,9 },
1692: { &INST_MOVEMRLEA,"MOVEM",1,0,5 },
1693: { &INST_MOVEAUSP,"MOVE2USP",1,1,0 },
1694: { &INST_MOVEUSPA,"MOVE USP,",1,1,0 },
1695:
1696: { &INST_ORSR,"ORSR",1,0,0 },
1697: { &INST_ANDSR,"ANDSR",1,0,0 },
1698: { &INST_EORSR,"EORSR",1,0,0 },
1699:
1700: { &INST_LINEA,"LINEA",0,0,0 },
1701: { &INST_LINEF,"LINEF",0,0,0 },
1702: { &INST_ILLG,"ILLEGAL",0,0,0 },
1703: { &INST_NIMP,"NOT IMPLEMENTED",0,0,0 },
1704: { NULL,NULL,0,0,0 }
1705: };
1706:
1707: static char* ccnames[] =
1708: { "T ","F ","HI","LS","CC","CS","NE","EQ",
1709: "VC","VS","PL","MI","GE","LT","GT","LE" };
1710:
1711: void MC68000_reset()
1712: {
1713: cout << "RESET!\n";
1714: regs.a[7] = (mem.get_word(0x00f80000) << 16) + mem.get_word(0xf80002);
1715: regs.pc = (mem.get_word(0x00f80004) << 16) + mem.get_word(0xf80006);
1716: regs.s = 1;
1717: regs.stopped = 0;
1718: instr_params p;
1719: INST_RESET(p);
1720: }
1721:
1722: void MC68000_step()
1723: {
1724: if (!regs.stopped) {
1725: UWORD opcode = nextiword();
1726: I_dec_tab_entry &dtentry = instr_dectab[opcode];
1727: dtentry.execfunc(dtentry.params);
1728: }
1729: for(int i=0;i<4;i++) clockcycle();
1730: int intr = intlev();
1731: if (intr != -1 && intr > regs.intmask) {
1732: Interrupt(intr);
1733: regs.stopped = 0;
1734: }
1735: }
1736:
1737: void MC68000_skip(CPTR nextpc)
1738: {
1739: do {
1740: MC68000_step();
1741: } while (nextpc != regs.pc);
1742: }
1743:
1744: void MC68000_disasm(CPTR addr,CPTR &nextpc,int cnt)
1745: {
1746:
1747: CPTR pc = regs.pc;
1748: regs.pc = addr;
1749: for (;cnt--;){
1750: cout << hex << setfill('0');
1751: char instrname[20],*ccpt;
1752: int opwords;
1753: cout << setw(8) << regs.pc << ": ";
1754: for(opwords=0;opwords<5;opwords++){
1755: cout << setw(4) << mem.get_word(regs.pc + opwords*2) << " ";
1756: }
1757: cout << dec;
1758:
1759: UWORD opcode = nextiword();
1760: I_dec_tab_entry &dtentry = instr_dectab[opcode];
1761: debug_entry *dp;
1762: for (dp = debugtbl;dp->f && dp->f != dtentry.execfunc;dp++)
1763: {}
1764:
1765: if (!dp->f) {
1766: cout << "PANIC OPCODE " << opcode << " AT " << addr;
1767: abort();
1768: }
1769: strcpy(instrname,dp->name);
1770: ccpt = strstr(instrname,"cc");
1771: if (ccpt != 0) {
1772: strncpy(ccpt,ccnames[dtentry.params.dest.reg],2);
1773: }
1774: cout << instrname;
1775: switch(dtentry.params.mask){
1776: case 0xff: cout << ".B "; break;
1777: case 0xffff: cout << ".W "; break;
1778: case 0xffffffff: cout << ".L "; break;
1779: }
1780: UWORD special = 0;
1781: if (dp->spc & 1) {
1782: special = nextiword();
1783: }
1784: if (dp->spc & 4) {
1785: cout << "#$" << hex << setw(4) << special << ",";
1786: }
1787: if (dp->src) {
1788: ShowEA(dtentry.params.src,dtentry.params.mask);
1789: }
1790: if (dp->src && dp->dest) cout << ",";
1791: if (dp->dest) {
1792: ShowEA(dtentry.params.dest,dtentry.params.mask);
1793: }
1794: if (dp->spc & 2) {
1795: special = nextiword();
1796: }
1797: if (dp->spc & 8) {
1798: cout << ",#$" << hex << setw(4) << special;
1799: }
1800: if (ccpt != 0) {
1801: cout << ( (cctrue(dtentry.params.dest.reg)) ? " (TRUE)" : " (FALSE)");
1802: }
1803: cout << "\n";
1804: }
1805: nextpc = regs.pc;
1806: regs.pc = pc;
1807: }
1808:
1809: void MC68000_dumpstate(CPTR &nextpc)
1810: {
1811: cout << hex << setfill('0');
1812:
1813: int i;
1814: for(i=0;i<8;i++){
1815: cout << "D" << setw(1) << i << ": " << setw(8) << regs.d[i] << " ";
1816: if ((i & 3) == 3) cout << "\n";
1817: }
1818: for(i=0;i<8;i++){
1819: cout << "A" << setw(1) << i << ": " << setw(8) << regs.a[i] << " ";
1820: if ((i & 3) == 3) cout << "\n";
1821: }
1822: cout << setw(1);
1823: cout << "T=" << regs.t << " S=" << regs.s << " X=" << regs.x << " N="
1824: << regs.n << " Z=" << regs.z << " V=" << regs.v << " C=" << regs.c
1825: << " IMASK=" << regs.intmask << "\n";
1826: MC68000_disasm(regs.pc,nextpc);
1827: cout << "next PC: " << setw(8) << hex << nextpc << "\n";
1828: }
1829:
1830: /*
1831: * GenerateDecTab() creates the instruction decode table.
1832: * FIXME: This should generate all legal instructions, but some illegal ones
1833: * will not be directed to INST_ILLG. On an accidental execution, a function
1834: * like GetEA() may call abort().
1835: *
1836: * This function is a monster and should probably be changed.
1837: */
1838:
1839: static void GenerateDecTab()
1840: {
1841: int offset;
1842: for(long int opcode=0;opcode<65536;opcode++){
1843: int r1 = (opcode & 0x0E00) >> 9;
1844: int m1 = (opcode & 0x01C0) >> 6;
1845: int m2 = (opcode & 0x0038) >> 3;
1846: int r2 = (opcode & 0x0007);
1847: int x = (m1 & 4) >> 2;
1848: int sz = (m1 & 3);
1849: addr_mode am1(m1,r1),am2(m2,r2);
1850: I_dec_tab_entry entry;
1851:
1852: switch(opcode & 0xF000) {
1853: case 0x0000:
1854: if (x) {
1855: if (am2.mode == Dreg || am2.mode == Aind ||
1856: am2.mode == Aipi || am2.mode == Apdi ||
1857: am2.mode == Ad16 || am2.mode == Ad8r ||
1858: am2.mode == absw || am2.mode == absl) {
1859: switch(sz){
1860: case 0:
1861: entry.execfunc = &INST_BTST;
1862: break;
1863: case 1:
1864: entry.execfunc = &INST_BCHG;
1865: break;
1866: case 2:
1867: entry.execfunc = &INST_BCLR;
1868: break;
1869: case 3:
1870: entry.execfunc = &INST_BSET;
1871: break;
1872: }
1873: entry.params.mask = 0xffffffff;
1874: am1 = am2;
1875: am2.mode = Dreg; am2.reg = r1;
1876: } else {
1877: entry.execfunc = &INST_NIMP; // MOVEP
1878: }
1879: } else {
1880: am1.mode = imm;
1881: if (sz == 3) {
1882: switch(r1){
1883: case 0:
1884: case 1:
1885: case 2:
1886: case 6:
1887: case 7:
1888: entry.execfunc = &INST_ILLG;
1889: break;
1890: case 3:
1891: entry.execfunc = &INST_NIMP; // RTM
1892: break;
1893: case 4:
1894: entry.execfunc = &INST_BSET;
1895: am1 = am2;
1896: am2.mode = imm;
1897: entry.params.mask = 0xffff;
1898: break;
1899: case 5:
1900: entry.execfunc = &INST_NIMP; // CAS
1901: break;
1902: }
1903: } else {
1904: entry.params.mask = sizemask(sz);
1905: switch(r1){
1906: case 0:
1907: if (am2.mode == imm)
1908: entry.execfunc = &INST_ORSR;
1909: else
1910: entry.execfunc = &INST_OR;
1911: break;
1912: case 1:
1913: if (am2.mode == imm)
1914: entry.execfunc = &INST_ANDSR;
1915: else
1916: entry.execfunc = &INST_AND;
1917: break;
1918: case 2:
1919: entry.execfunc = &INST_SUB;
1920: break;
1921: case 3:
1922: entry.execfunc = &INST_ADD;
1923: break;
1924: case 4:
1925: switch(sz){
1926: case 0: entry.execfunc = &INST_BTST; break;
1927: case 1: entry.execfunc = &INST_BCHG; break;
1928: case 2: entry.execfunc = &INST_BCLR; break;
1929: }
1930: entry.params.mask = 0xffff;
1931: break;
1932: case 5:
1933: if (am2.mode == imm)
1934: entry.execfunc = &INST_EORSR;
1935: else
1936: entry.execfunc = &INST_EOR;
1937: break;
1938: case 6:
1939: entry.execfunc = &INST_CMP;
1940: break;
1941: case 7:
1942: entry.execfunc = &INST_NIMP; // MOVES
1943: break;
1944: }
1945: am1 = am2; am2.mode = imm;
1946: }
1947: }
1948: break;
1949: case 0x1000:
1950: switch(am1.mode) {
1951: case Areg: case imm: case imm3: case ill2: case ill3:
1952: entry.execfunc = &INST_ILLG; // MOVEA.B ???
1953: break;
1954: default:
1955: entry.execfunc = &INST_MOVE; // MOVE.B
1956: break;
1957: }
1958: entry.params.mask = 0xff;
1959: break;
1960: case 0x2000:
1961: switch(am1.mode) {
1962: case Areg:
1963: entry.execfunc = &INST_MOVEA; // MOVEA.L
1964: break;
1965: case imm: case imm3: case ill2: case ill3:
1966: entry.execfunc = &INST_ILLG;
1967: break;
1968: default:
1969: entry.execfunc = &INST_MOVE; // MOVE.L
1970: break;
1971: }
1972: entry.params.mask = 0xffffffff;
1973: break;
1974: case 0x3000:
1975: switch(am1.mode) {
1976: case Areg:
1977: entry.execfunc = &INST_MOVEA; // MOVEA.W
1978: break;
1979: case imm: case imm3: case ill2: case ill3:
1980: entry.execfunc = &INST_ILLG;
1981: break;
1982: default:
1983: entry.execfunc = &INST_MOVE; // MOVE.W
1984: break;
1985: }
1986: entry.params.mask = 0xffff;
1987: break;
1988: case 0x4000:
1989: if (x){
1990: switch(sz){
1991: case 0:
1992: entry.execfunc = &INST_CHK;
1993: entry.params.mask = 0xffffffff;
1994: am1.mode = Dreg; am1.reg = r1;
1995: break;
1996: case 1:
1997: entry.execfunc = &INST_ILLG;
1998: break;
1999: case 2:
2000: entry.execfunc = &INST_CHK;
2001: entry.params.mask = 0xffff;
2002: am1.mode = Dreg; am1.reg = r1;
2003: break;
2004: case 3:
2005: if (am2.mode == Dreg) {
2006: entry.execfunc = &INST_NIMP; // EXTB.L
2007: } else {
2008: entry.execfunc = &INST_LEA;
2009: entry.params.mask = 0xffffffff;
2010: am1.mode = Areg; am1.reg = r1;
2011: }
2012: break;
2013: }
2014: } else {
2015: switch(sz){
2016: case 0:
2017: switch(r1){
2018: case 0:
2019: entry.execfunc = &INST_NEG;
2020: entry.params.mask = 0xff;
2021: break;
2022: case 1:
2023: entry.execfunc = &INST_CLR;
2024: entry.params.mask = 0xff;
2025: break;
2026: case 2:
2027: entry.execfunc = &INST_NEG;
2028: entry.params.mask = 0xff;
2029: break;
2030: case 3:
2031: entry.execfunc = &INST_NOT;
2032: entry.params.mask = 0xff;
2033: break;
2034: case 4:
2035: if (am2.mode == Areg) {
2036: entry.execfunc = &INST_LINK; // this is from 020 upwards
2037: entry.params.mask = 0xffffffff;
2038: am1.mode = imm;
2039: } else {
2040: entry.execfunc = &INST_NBCD;
2041: entry.params.mask = 0xff;
2042: }
2043: break;
2044: case 5:
2045: entry.execfunc = &INST_TST;
2046: entry.params.mask = 0xff;
2047: break;
2048: case 6:
2049: entry.execfunc = &INST_NIMP; // MUL[US].L
2050: break;
2051: case 7:
2052: entry.execfunc = &INST_ILLG;
2053: break;
2054: }
2055: break;
2056: case 1:
2057: switch(r1){
2058: case 0:
2059: entry.execfunc = &INST_NEG;
2060: entry.params.mask = 0xffff;
2061: break;
2062: case 1:
2063: entry.execfunc = &INST_CLR;
2064: entry.params.mask = 0xffff;
2065: break;
2066: case 2:
2067: entry.execfunc = &INST_NEG;
2068: entry.params.mask = 0xffff;
2069: break;
2070: case 3:
2071: entry.execfunc = &INST_NOT;
2072: entry.params.mask = 0xffff;
2073: break;
2074: case 4:
2075: if (am2.mode == Dreg) {
2076: entry.execfunc = &INST_SWAP;
2077: entry.params.mask = 0xffffffff;
2078: } else {
2079: entry.execfunc = &INST_LEA; // PEA == LEA ea,-(A7)
2080: entry.params.mask = 0xffffffff;
2081: am1.mode = Apdi;
2082: am1.reg = 7;
2083: }
2084: break;
2085: case 5:
2086: entry.execfunc = &INST_TST;
2087: entry.params.mask = 0xffff;
2088: break;
2089: case 6:
2090: entry.execfunc = &INST_NIMP; // DIV[US]{L}.L
2091: break;
2092: case 7:
2093: switch(am2.mode){
2094: case Areg: case Dreg:
2095: entry.execfunc = &INST_TRAP;
2096: break;
2097: case Aind:
2098: entry.execfunc = &INST_LINK;
2099: am1.mode = imm;
2100: am2.mode = Areg;
2101: entry.params.mask = 0xffff;
2102: break;
2103: case Aipi:
2104: entry.execfunc = &INST_UNLK;
2105: am2.mode = Areg;
2106: break;
2107: case Apdi:
2108: entry.execfunc = &INST_MOVEAUSP;
2109: am2.mode = Areg;
2110: break;
2111: case Ad16:
2112: entry.execfunc = &INST_MOVEUSPA;
2113: am2.mode = Areg;
2114: break;
2115: case Ad8r:
2116: am2.mode = imm;
2117: switch(am2.reg){
2118: case 0: entry.execfunc = &INST_RESET; break;
2119: case 1: entry.execfunc = &INST_NOP; break;
2120: case 2: entry.execfunc = &INST_STOP; break;
2121: case 3: entry.execfunc = &INST_RTE; break;
2122: case 4: entry.execfunc = &INST_RTD; break;
2123: case 5: entry.execfunc = &INST_RTS; break;
2124: case 6: entry.execfunc = &INST_TRAPV; break;
2125: case 7: entry.execfunc = &INST_RTR; break;
2126: }
2127: break;
2128: case absw: case absl: case PC16: case PC8r: case imm:
2129: case imm3: case ill2: case ill3:
2130: entry.execfunc = &INST_ILLG;
2131: break;
2132: }
2133: }
2134: break;
2135: case 2:
2136: switch(r1){
2137: case 0:
2138: entry.execfunc = &INST_NEG;
2139: entry.params.mask = 0xffffffff;
2140: break;
2141: case 1:
2142: entry.execfunc = &INST_CLR;
2143: entry.params.mask = 0xffffffff;
2144: break;
2145: case 2:
2146: entry.execfunc = &INST_NEG;
2147: entry.params.mask = 0xffffffff;
2148: break;
2149: case 3:
2150: entry.execfunc = &INST_NOT;
2151: entry.params.mask = 0xffffffff;
2152: break;
2153: case 4:
2154: entry.params.mask = 0xffff;
2155: if (am2.mode == Dreg) {
2156: entry.execfunc = &INST_EXTW;
2157: } else {
2158: entry.execfunc = &INST_MOVEMRLEA;
2159: }
2160: break;
2161: case 5:
2162: entry.execfunc = &INST_TST;
2163: entry.params.mask = 0xffffffff;
2164: break;
2165: case 6:
2166: entry.params.mask =0xffff;
2167: entry.execfunc = &INST_MOVEMEARL;
2168: break;
2169: case 7:
2170: entry.params.mask =0xffffffff;
2171: if (am2.mode == imm) {
2172: entry.execfunc = &INST_ILLG;
2173: } else {
2174: entry.execfunc = &INST_JSR;
2175: }
2176: break;
2177: }
2178: break;
2179: case 3:
2180: entry.params.mask = 0xffff;
2181: switch(r1){
2182: case 0:
2183: entry.execfunc = &INST_MOVESREA;
2184: break;
2185: case 1:
2186: entry.execfunc = &INST_MOVECCREA;
2187: break;
2188: case 2:
2189: entry.execfunc = &INST_MOVEEACCR;
2190: break;
2191: case 3:
2192: entry.execfunc = &INST_MOVEEASR;
2193: break;
2194: case 4:
2195: entry.params.mask = 0xffffffff;
2196: if (am2.mode == Dreg) {
2197: entry.execfunc = &INST_EXTL;
2198: } else {
2199: entry.execfunc = &INST_MOVEMRLEA;
2200: }
2201: break;
2202: case 5:
2203: entry.execfunc = &INST_NIMP; // TAS.B
2204: break;
2205: case 6:
2206: entry.params.mask =0xffffffff;
2207: entry.execfunc = &INST_MOVEMEARL;
2208: break;
2209: case 7:
2210: entry.params.mask =0xffffffff;
2211: if (am2.mode == imm) {
2212: entry.execfunc = &INST_ILLG;
2213: } else {
2214: entry.execfunc = &INST_JMP;
2215: }
2216: break;
2217: }
2218: break;
2219: }
2220: }
2221: break;
2222: case 0x5000:
2223: switch(sz){
2224: case 0: case 1: case 2:
2225: entry.params.mask = sizemask(sz);
2226: if (x) {
2227: if (am2.mode == Areg)
2228: entry.execfunc = &INST_SUBA/*Q*/;
2229: else
2230: entry.execfunc = &INST_SUB/*Q*/;
2231:
2232: } else {
2233: if (am2.mode == Areg)
2234: entry.execfunc = &INST_ADDA/*Q*/;
2235: else
2236: entry.execfunc = &INST_ADD/*Q*/;
2237: }
2238: am1 = am2; am2.mode = imm3; am2.reg = r1 ? r1 : 8;
2239: break;
2240: case 3:
2241: if (am2.mode == Areg) {
2242: entry.params.mask = 0xffff;
2243: entry.execfunc = &INST_DBcc;
2244: am2.mode = Dreg;
2245: } else {
2246: entry.params.mask = 0xff;
2247: entry.execfunc = &INST_Scc;
2248: }
2249: am1.mode = imm3;
2250: am1.reg = (opcode & 0xf00) >> 8;
2251: }
2252: break;
2253: case 0x6000:
2254: offset = opcode & 0xff;
2255: if (x == 1 && r1 == 0) {
2256: if (offset == 0) {
2257: entry.execfunc = &INST_BSRW;
2258: entry.params.mask = 0xffff;
2259: am2.mode = imm;
2260: } else {
2261: entry.execfunc = &INST_BSRB;
2262: entry.params.mask = 0xff;
2263: am2.mode = imm3; am2.reg = opcode & 0xff;
2264: }
2265: } else {
2266: if (offset == 0) {
2267: entry.execfunc = &INST_BccW;
2268: entry.params.mask = 0xffff;
2269: am2.mode = imm;
2270: } else {
2271: entry.execfunc = &INST_BccB;
2272: entry.params.mask = 0xff;
2273: am2.mode = imm3; am2.reg = opcode & 0xff;
2274: }
2275: }
2276: am1.reg = (opcode & 0xf00) >> 8;
2277: break;
2278: case 0x7000:
2279: if (x) {
2280: entry.execfunc = &INST_ILLG;
2281: } else {
2282: entry.execfunc = &INST_MOVEQ;
2283: am1.mode = Dreg; am1.reg = r1; entry.params.mask = 0xffffffff;
2284: am2.mode = imm3; am2.reg = opcode & 0xff;
2285: }
2286: break;
2287: case 0x8000:
2288: if (x) {
2289: switch(sz) {
2290: case 0: case 1: case 2:
2291: entry.params.mask = sizemask(sz);
2292: switch (am2.mode) {
2293: case Dreg:
2294: if (sz != 0) {
2295: entry.execfunc = &INST_NIMP; // PACK, UNPK
2296: } else {
2297: entry.execfunc = &INST_SBCD;
2298: entry.params.mask = 0xff;
2299: am1.mode = Dreg;
2300: am1.reg = r1;
2301: }
2302: break;
2303: case Areg:
2304: if (sz != 0) {
2305: entry.execfunc = &INST_NIMP; // PACK, UNPK
2306: } else {
2307: entry.execfunc = &INST_SBCD;
2308: entry.params.mask = 0xff;
2309: am1.mode = am2.mode = Apdi;
2310: am1.reg = r1;
2311: }
2312: break;
2313: default:
2314: entry.execfunc = &INST_OR;
2315: am1 = am2; am2.mode = Dreg; am2.reg = r1;
2316: break;
2317: }
2318: break;
2319: case 3:
2320: entry.execfunc = &INST_DIVS;
2321: entry.params.mask = 0xffff;
2322: am1.mode = Dreg; am1.reg = r1;
2323: break;
2324: }
2325: } else {
2326: am1.mode = Dreg; am1.reg = r1;
2327: switch(sz) {
2328: case 0: case 1: case 2:
2329: entry.execfunc = &INST_OR;
2330: entry.params.mask = sizemask(sz);
2331: break;
2332: case 3:
2333: entry.execfunc = &INST_DIVU;
2334: entry.params.mask = 0xffff;
2335: break;
2336: }
2337: }
2338: break;
2339: case 0x9000:
2340: if (sz == 3) {
2341: entry.execfunc = &INST_SUBA;
2342: entry.params.mask = x ? 0xffffffff : 0xffff;
2343: am1.mode = Areg; am1.reg = r1;
2344: } else {
2345: entry.execfunc = &INST_SUB;
2346: entry.params.mask = sizemask(sz);
2347: if (x) {
2348: switch(am2.mode) {
2349: case Dreg:
2350: entry.execfunc = &INST_SUBX;
2351: am1.mode = Dreg;
2352: am1.reg = r1;
2353: break;
2354: case Areg:
2355: entry.execfunc = &INST_SUBX;
2356: am1.mode = am2.mode = Apdi;
2357: am1.reg = r1;
2358: break;
2359: default:
2360: am1 = am2;
2361: am2.mode = Dreg;
2362: am2.reg = r1;
2363: break;
2364: }
2365: } else {
2366: am1.mode = Dreg;
2367: am1.reg = r1;
2368: }
2369: }
2370: break;
2371: case 0xA000:
2372: entry.execfunc = &INST_LINEA;
2373: break;
2374: case 0xB000:
2375: if (sz == 3) {
2376: entry.execfunc = &INST_CMPA;
2377: entry.params.mask = x ? 0xffffffff : 0xffff;
2378: am1.mode = Areg; am1.reg = r1;
2379: } else {
2380: entry.params.mask = sizemask(sz);
2381: am1.mode = Dreg; am1.reg = r1;
2382: if (x) {
2383: if (am2.mode == Areg){
2384: am1.mode = am2.mode = Aipi;
2385: am1.reg = r1;
2386: entry.execfunc = &INST_CMP/*M*/;
2387: } else {
2388: entry.execfunc = &INST_EOR;
2389: am1 = am2; am2.mode = Dreg; am2.reg = r1;
2390: }
2391: } else {
2392: entry.execfunc = &INST_CMP;
2393: }
2394: }
2395: break;
2396: case 0xC000:
2397: if (x) {
2398: switch(sz) {
2399: case 0: case 1: case 2:
2400: entry.params.mask = sizemask(sz);
2401: switch (am2.mode) {
2402: case Dreg:
2403: switch(sz) {
2404: case 2:
2405: entry.execfunc = &INST_ILLG;
2406: break;
2407: case 1:
2408: entry.execfunc = &INST_EXGL;
2409: entry.params.mask = 0xffffffff;
2410: am1 = am2;
2411: am2.mode = Dreg; am2.reg = r1;
2412: break;
2413: case 0:
2414: entry.execfunc = &INST_ABCD;
2415: entry.params.mask = 0xff;
2416: am1.mode = Dreg; am1.reg = r1;
2417: break;
2418: }
2419: break;
2420: case Areg:
2421: switch(sz) {
2422: case 2:
2423: entry.execfunc = &INST_EXGL;
2424: entry.params.mask = 0xffffffff;
2425: am1 = am2;
2426: am2.mode = Dreg; am2.reg = r1;
2427: break;
2428: case 1:
2429: entry.execfunc = &INST_EXGL;
2430: entry.params.mask = 0xffffffff;
2431: am1 = am2;
2432: am2.mode = Areg; am2.reg = r1;
2433: break;
2434: case 0:
2435: entry.execfunc = &INST_ABCD;
2436: entry.params.mask = 0xff;
2437: am1.mode = am2.mode = Apdi;
2438: am1.reg = r1;
2439: break;
2440: }
2441: break;
2442: default:
2443: entry.execfunc = &INST_AND;
2444: am1 = am2;
2445: am2.mode = Dreg; am2.reg = r1;
2446: break;
2447: }
2448: break;
2449: case 3:
2450: entry.execfunc = &INST_MULS;
2451: entry.params.mask = 0xffff;
2452: am1.mode = Dreg; am1.reg = r1;
2453: break;
2454: }
2455: } else {
2456: am1.mode = Dreg; am1.reg = r1;
2457: switch(sz) {
2458: case 0: case 1: case 2:
2459: entry.execfunc = &INST_AND;
2460: entry.params.mask = sizemask(sz);
2461: break;
2462: case 3:
2463: entry.execfunc = &INST_MULU;
2464: entry.params.mask = 0xffff;
2465: break;
2466: }
2467: }
2468: break;
2469: case 0xD000:
2470: if (sz == 3) {
2471: entry.execfunc = &INST_ADDA;
2472: entry.params.mask = x ? 0xffffffff : 0xffff;
2473: am1.mode = Areg; am1.reg = r1;
2474: } else {
2475: entry.execfunc = &INST_ADD;
2476: entry.params.mask = sizemask(sz);
2477: if (x) {
2478: switch(am2.mode) {
2479: case Dreg:
2480: entry.execfunc = &INST_ADDX;
2481: am1.mode = Dreg;
2482: am1.reg = r1;
2483: break;
2484: case Areg:
2485: entry.execfunc = &INST_ADDX;
2486: am1.mode = am2.mode = Apdi;
2487: am1.reg = r1;
2488: break;
2489: default:
2490: am1 = am2;
2491: am2.mode = Dreg;
2492: am2.reg = r1;
2493: break;
2494: }
2495: } else {
2496: am1.mode = Dreg;
2497: am1.reg = r1;
2498: }
2499: }
2500: break;
2501: case 0xE000:
2502: int type;
2503:
2504: if (sz == 3) {
2505: entry.params.mask = 0xffff;
2506: type = r1*2 + x;
2507: switch(type) {
2508: case 0: entry.execfunc = &INST_ASR1; break;
2509: case 1: entry.execfunc = &INST_ASL1; break;
2510: case 2: entry.execfunc = &INST_LSR1; break;
2511: case 3: entry.execfunc = &INST_LSL1; break;
2512: case 4: entry.execfunc = &INST_ROXR1; break;
2513: case 5: entry.execfunc = &INST_ROXL1; break;
2514: case 6: entry.execfunc = &INST_ROR1; break;
2515: case 7: entry.execfunc = &INST_ROL1; break;
2516: default:
2517: entry.execfunc = &INST_NIMP; // 020 bit fiends
2518: break;
2519: }
2520: if (type < 8) {
2521: if (am2.mode == Dreg || am2.mode == Areg || am2.mode == PC16 ||
2522: am2.mode == PC8r || am2.mode == imm) {
2523: entry.execfunc = &INST_ILLG;
2524: }
2525: }
2526: am1 = am2;
2527: } else {
2528: type = x + (m2 & 3)*2;
2529: entry.params.mask = sizemask(sz);
2530: switch(type) {
2531: case 0: entry.execfunc = &INST_ASR; break;
2532: case 1: entry.execfunc = &INST_ASL; break;
2533: case 2: entry.execfunc = &INST_LSR; break;
2534: case 3: entry.execfunc = &INST_LSL; break;
2535: case 4: entry.execfunc = &INST_ROXR; break;
2536: case 5: entry.execfunc = &INST_ROXL; break;
2537: case 6: entry.execfunc = &INST_ROR; break;
2538: case 7: entry.execfunc = &INST_ROL; break;
2539: }
2540: am1.mode = Dreg; am1.reg = r2;
2541: if (m2 > 3) {
2542: am2.mode = Dreg; am2.reg = r1;
2543: } else {
2544: am2.mode = imm3;
2545: am2.reg = r1 ? r1 : 8;
2546: }
2547: }
2548: break;
2549: case 0xF000:
2550: entry.execfunc = &INST_LINEF;
2551: break;
2552: }
2553: entry.params.dest = am1; entry.params.src = am2;
2554: instr_dectab[opcode] = entry;
2555: }
2556: // Mahlzeit!
2557: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.