|
|
1.1 root 1: //
2: // nono
1.1.1.2 ! root 3: // Copyright (C) 2020 nono project
! 4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.2 ! root 7: #include "m88100acc.h"
! 8:
1.1 root 9: // 命令のフィールド取り出し
1.1.1.2 ! root 10: #define FLD_D m88100opf_D(opX)
! 11: #define FLD_S1 m88100opf_S1(opX)
! 12: #define FLD_S2 m88100opf_S2(opX)
! 13: #define FLD_CR m88100opf_CR(opX)
! 14: #define B5 m88100opf_B5(opX)
! 15: #define M5 m88100opf_M5(opX)
! 16: #define W5 m88100opf_W5(opX)
! 17: #define O5 m88100opf_O5(opX)
! 18: #define IMM16 m88100opf_IMM16(opX)
! 19: #define VEC9 m88100opf_VEC9(opX)
1.1 root 20:
21: // 符号拡張・シフト済みのディスプレースメント
22: // XXX: (負数の右シフト)GCC only
23: #define D16 (((int32)(int16)opX) << 2)
24: #define D26 (((int32)(opX << 6) >> 4))
25: #define IsCO ((opX >> 8) & 1)
26: #define IsCI ((opX >> 9) & 1)
27:
28: // レジスタアクセス
29: #define rD (r[FLD_D])
30: #define rS1 (r[FLD_S1])
31: #define rS2 (r[FLD_S2])
32:
33:
34: // ブランチ命令入り口
35: inline void
36: m88kcpu::EnterBranch()
37: {
38: }
39:
1.1.1.2 ! root 40: // ブランチ本体
! 41: inline void
! 42: m88kcpu::DoBranch(uint32 toaddr)
! 43: {
! 44: // ブランチヒストリに登録しつつ、
! 45: // ブランチヒストリからブランチ状況を取得
! 46: auto e = brhist.AddEntry(xip, toaddr);
! 47: fip = toaddr;
! 48:
! 49: // STOP 検出。
! 50: // m88k には STOP 状態 (何もせず割り込みだけ待つ状態。m68k の STOP 命令
! 51: // による STOP 状態に相当するもの) は存在せず、割り込みが起きるまで NOP
! 52: // 相当の命令を無限ループで実行し続ける方法が一般的にとられる。
! 53: // 実機であれば (電力が無駄なこと以外は) これで特段困らないかも知れないが
! 54: // エミュレータ (特に高速モード) ではこのような無限ループはホストの CPU
! 55: // がぶん回る状況になるため避けたい。そのためこの無限ループを検出したい。
! 56: // ただし特定の(または定番の)命令列があるわけではなく、任意の無限ループが
! 57: // 用いられているため、汎用的に自動検出する必要がある。
! 58:
! 59: // ループの 1 回目のブランチで初期化して、
! 60: // 2 回目のブランチで STOP だったかどうかをチェックする。
! 61: // 3 回目以降の場合は STOP でなかったので、もうチェックする必要はない。
! 62:
! 63: // m68k の STOP 命令が特権命令なので、それに倣ってここでも特権状態のみを
! 64: // 対象とする。
! 65:
! 66: // 通常のブランチで来る回数がはるかに多いと考えられるので、
! 67: // 先にカウント数をチェック対象かどうか調べる。
! 68: if (e.count < 3 && IsSuper()) {
! 69: if (e.count == 1) {
! 70: // 新規ブランチ
! 71: // 初期化
! 72: nop_counter = 0;
! 73: } else {
! 74: // e.count == 2 のときだけ STOP の検証をすれば良い。
! 75:
! 76: // d はブランチ間の命令数
! 77: uint32 d = (xip - toaddr) / sizeof(uint32);
! 78: // 遅延ブランチなら 1 命令余分に実行するはずなので 1 足す
! 79: if (opX & (1 << 26)) {
! 80: d++;
! 81: }
! 82: // ブランチ間の命令がすべて NOP なら STOP ということにする。
! 83: if (nop_counter == d) {
! 84: atomic_reqflag |= CPU_REQ_STOP;
! 85: }
! 86: }
! 87: // STOP ではなかったら、あとは放置していい
! 88: }
! 89: }
! 90:
1.1 root 91: // 通常(即時)ブランチ出口
92: inline void
93: m88kcpu::ExitBranch()
94: {
95: // re-fetch branched instruction
96: fetch();
97: }
98:
99: // 遅延ブランチ出口
100: inline void
101: m88kcpu::ExitDelayBranch()
102: {
103: opF = OpSetDelay(opF);
104: }
105:
106: // ロードストアユニットの usr の処理。
107: // 正常なら true を返す (ので呼び出し側は実行継続)、
108: // 例外が起きたら処理して false を返すので呼び出し側は即リターンすること。
109: inline bool
1.1.1.2 ! root 110: m88kcpu::ldst_usr(uint32& usr)
1.1 root 111: {
112: usr = (opX & (1 << 8)) ? DM_USR : 0;
113: if (IsUser() && usr) {
114: Exception(M88K_EXCEP_PRIV);
115: return false;
116: }
117: return true;
118: }
119:
1.1.1.2 ! root 120: // MEMO: ロードストアでの usr の処理で、CMMU に対して
! 121: // usr を引数ではなくSetSuper() の呼び出しで渡すようにしている。
! 122: // データのロードストアだけがあるのなら usr を引数で渡すほうが
! 123: // 効率的だが、CMMU は 命令/データで同じものを使うため、
! 124: // 命令 CMMU では 100% 無駄な引数の引き渡しが必要になってしまう。
! 125: // そして命令アクセスのほうが何倍も比率が多い。
! 126: // .usr 指定は比率としてはレアなので、状態変更メソッドによる
! 127: // 方法にしてみた。
! 128:
1.1 root 129: // ロードストアユニットの scale の処理。addr を返す。
130: inline uint32
131: m88kcpu::ldst_scale(uint32 size)
132: {
133: if (opX & (1 << 9)) {
134: return rS1 + rS2 * size;
135: } else {
136: return rS1 + rS2;
137: }
138: }
139:
140: // ロードストアユニットの align の処理。
141: // 正常なら true を返す (ので呼び出し側は実行継続)、
142: // 例外が起きたら処理して false を返すので呼び出し側は即リターンすること。
143: inline bool
144: m88kcpu::ldst_align(uint32 size, uint32& addr)
145: {
146: if (addr & (size - 1)) {
147: if (IsMXM()) {
148: addr &= ~(size - 1);
149: } else {
150: Exception(M88K_EXCEP_MISALIGNED);
151: return false;
152: }
153: }
154: return true;
155: }
156:
157: // ロードストアユニットの usr と scale の処理 (呼び出し用マクロ)
158: #define LDST_USR_SCALE(size) do { \
1.1.1.2 ! root 159: if (ldst_usr(usr) == false) \
1.1 root 160: return; \
161: addr = ldst_scale(size); \
162: } while (0)
163:
164: // ロードストアユニットの align の処理 (呼び出し用マクロ)
165: #define LDST_ALIGN(size) do { \
166: if (ldst_align(size, addr) == false) \
167: return; \
168: } while (0)
169:
170: // ロードストアユニットのまとめたもの
171: #define LDST_USR_SCALE_ALIGN(size) do { \
172: LDST_USR_SCALE(size); \
173: LDST_ALIGN(size); \
174: } while (0)
175:
176: // 幅規制付き算術左シフト
177: static inline uint32
178: ASL(uint32 a, int n)
179: {
180: if (n <= 0)
181: return a;
182: if (n >= 32)
183: return 0;
184: return a << n;
185: }
186:
187: // 幅規制付き算術右シフト
188: static inline uint32
189: ASR(uint32 a, int n)
190: {
191: if (n <= 0)
192: return a;
193: if (n >= 32)
194: return (int32)a < 0 ? -1 : 0;
195: // XXX: 負数の右シフト
196: return (int32)a >> n;
197: }
198:
199: // 幅規制付き論理右シフト
200: static inline uint32
201: LSR(uint32 a, int n)
202: {
203: if (n <= 0)
204: return a;
205: if (n >= 32)
206: return 0;
207: return a >> n;
208: }
209:
210:
211: // 右ローテート
212: static inline uint32
213: ROR(uint32 a, int n)
214: {
215: // TODO: 各種コンパイラごとにビルトインがあったりなかったりするらしい
216: n &= 31;
217: if (n == 0) {
218: return a;
219: } else {
220: return (a >> n) | (a << (32 - n));
221: }
222: }
223:
224: // add でのオーバーフロー条件
225: static inline bool
226: isovf_add(uint32 s1, uint32 s2, uint32 res)
227: {
228: return (int32)((s1 ^ res) & (s2 ^ res)) < 0;
229: }
230: // sub でのオーバーフロー条件
231: static inline bool
232: isovf_sub(uint32 s1, uint32 s2, uint32 res)
233: {
234: return (int32)((s1 ^ s2) & (s1 ^ res)) < 0;
235: }
236:
237: // bcnd のやつ
238: static inline int
239: acc_cnd(uint32 r)
240: {
241: int rv;
242: if (r & 0x80000000) {
243: if (r == 0x80000000) {
244: rv = 0x8;
245: } else {
246: rv = 0x4;
247: }
248: } else {
249: if (r == 0) {
250: rv = 0x2;
251: } else {
252: rv = 0x1;
253: }
254: }
255: return rv;
256: }
257:
258: // bitfield
259: static inline uint32
260: acc_bf(int w, int ofs)
261: {
262: uint32 m;
263: if (w == 0) {
264: m = 0xFFFFFFFFU;
265: } else {
266: m = ~(0xFFFFFFFFU << w);
267: }
268: return m << ofs;
269: }
270:
271: // ここから命令定義
272:
273: // 000000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
274: OP_DEF(xmem_bu_imm)
275: {
276: uint32 addr;
277: uint64 tmp;
278:
279: addr = rS1 + IMM16;
280: LDST_ALIGN(1);
281:
282: lastaddr = addr;
1.1.1.2 ! root 283: tmp = cmmu[1].xmem_8(addr, rD);
1.1 root 284: if ((int64)tmp < 0) {
1.1.1.2 ! root 285: XmemDataException(addr, rD, DM_BU | DM_LOCK);
1.1 root 286: return;
287: }
288: if (FLD_D == 0)
289: return;
290: rD = tmp;
291: }
292:
293: // 000001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
294: OP_DEF(xmem_w_imm)
295: {
296: uint32 addr;
297: uint64 tmp;
298:
299: addr = rS1 + IMM16;
300: LDST_ALIGN(4);
301:
302: lastaddr = addr;
1.1.1.2 ! root 303: tmp = cmmu[1].xmem_32(addr, rD);
1.1 root 304: if ((int64)tmp < 0) {
1.1.1.2 ! root 305: XmemDataException(addr, rD, DM_W | DM_LOCK);
1.1 root 306: return;
307: }
308: if (FLD_D == 0)
309: return;
310: rD = tmp;
311: }
312:
313: // 000010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
314: OP_DEF(ld_hu_imm)
315: {
316: uint32 addr;
317: uint64 tmp;
318:
319: addr = rS1 + IMM16;
320: LDST_ALIGN(2);
321:
322: lastaddr = addr;
323: tmp = cmmu[1].load_16(addr);
324: if ((int64)tmp < 0) {
325: ReadDataException(addr, DM_HU);
326: return;
327: }
328: if (FLD_D == 0)
329: return;
330: rD = tmp;
331: }
332:
333: // 000011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
334: OP_DEF(ld_bu_imm)
335: {
336: uint32 addr;
337: uint64 tmp;
338:
339: addr = rS1 + IMM16;
340: LDST_ALIGN(1);
341:
342: lastaddr = addr;
343: tmp = cmmu[1].load_8(addr);
344: if ((int64)tmp < 0) {
345: ReadDataException(addr, DM_BU);
346: return;
347: }
348: if (FLD_D == 0)
349: return;
350: rD = tmp;
351: }
352:
353: // 000100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
354: OP_DEF(ld_d_imm)
355: {
356: uint32 addr;
357: uint64 tmp, tmp2;
358:
359: addr = rS1 + IMM16;
360: LDST_ALIGN(8);
361:
362: lastaddr = addr;
363: tmp = cmmu[1].load_32(addr);
364: if ((int64)tmp < 0) {
365: ReadDataException(addr, DM_D1);
366: return;
367: }
368: addr += 4;
369: tmp2 = cmmu[1].load_32(addr);
370: if ((int64)tmp2 < 0) {
371: ReadDataException(addr, DM_D2);
372: return;
373: }
374:
375: rD = tmp;
376: r[(FLD_D + 1) & 0x1f] = tmp2;
377: r[0] = 0;
378: }
379:
380: // 000101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
381: OP_DEF(ld_w_imm)
382: {
383: uint32 addr;
384: uint64 tmp;
385:
386: addr = rS1 + IMM16;
387: LDST_ALIGN(4);
388:
389: lastaddr = addr;
390: tmp = cmmu[1].load_32(addr);
391: if ((int64)tmp < 0) {
392: ReadDataException(addr, DM_W);
393: return;
394: }
395: if (FLD_D == 0)
396: return;
397: rD = tmp;
398: }
399:
400: // 000110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
401: OP_DEF(ld_h_imm)
402: {
403: uint32 addr;
404: uint64 tmp;
405:
406: addr = rS1 + IMM16;
407: LDST_ALIGN(2);
408:
409: lastaddr = addr;
410: tmp = cmmu[1].load_16(addr);
411: if ((int64)tmp < 0) {
412: ReadDataException(addr, DM_H);
413: return;
414: }
415: if (FLD_D == 0)
416: return;
417: rD = (uint32)(int32)(int16)tmp;
418: }
419:
420: // 000111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
421: OP_DEF(ld_b_imm)
422: {
423: uint32 addr;
424: uint64 tmp;
425:
426: addr = rS1 + IMM16;
427: LDST_ALIGN(1);
428:
429: lastaddr = addr;
430: tmp = cmmu[1].load_8(addr);
431: if ((int64)tmp < 0) {
432: ReadDataException(addr, DM_B);
433: return;
434: }
435: if (FLD_D == 0)
436: return;
437: rD = (uint32)(int32)(int8)tmp;
438: }
439:
440: // 001000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
441: OP_DEF(st_d_imm)
442: {
443: uint32 addr;
444:
445: addr = rS1 + IMM16;
446: LDST_ALIGN(8);
447:
448: lastaddr = addr;
449: if ((int64)cmmu[1].store_32(addr, rD) < 0) {
450: WriteDataException(addr, rD, DM_D1);
451: return;
452: }
453: addr += 4;
454: if ((int64)cmmu[1].store_32(addr, r[(FLD_D + 1) & 0x1f]) < 0) {
455: WriteDataException(addr, r[(FLD_D + 1) & 0x1f], DM_D2);
456: return;
457: }
458: }
459:
460: // 001001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
461: OP_DEF(st_w_imm)
462: {
463: uint32 addr;
464:
465: addr = rS1 + IMM16;
466: LDST_ALIGN(4);
467:
468: lastaddr = addr;
469: if ((int64)cmmu[1].store_32(addr, rD) < 0) {
470: WriteDataException(addr, rD, DM_W);
471: return;
472: }
473: }
474:
475: // 001010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
476: OP_DEF(st_h_imm)
477: {
478: uint32 addr;
479:
480: addr = rS1 + IMM16;
481: LDST_ALIGN(2);
482:
483: lastaddr = addr;
484: if ((int64)cmmu[1].store_16(addr, rD) < 0) {
485: WriteDataException(addr, rD, DM_H);
486: return;
487: }
488: }
489:
490: // 001011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
491: OP_DEF(st_b_imm)
492: {
493: uint32 addr;
494:
495: addr = rS1 + IMM16;
496: LDST_ALIGN(1);
497:
498: lastaddr = addr;
499: if ((int64)cmmu[1].store_8(addr, rD) < 0) {
500: WriteDataException(addr, rD, DM_B);
501: return;
502: }
503: }
504:
505: // 001100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
506: OP_DEF(lda_d_imm)
507: {
508: if (FLD_D == 0)
509: return;
510: rD = rS1 + IMM16;
511: }
512:
513: // 001101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
514: OP_DEF(lda_w_imm)
515: {
516: if (FLD_D == 0)
517: return;
518: rD = rS1 + IMM16;
519: }
520:
521: // 001110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
522: OP_DEF(lda_h_imm)
523: {
524: if (FLD_D == 0)
525: return;
526: rD = rS1 + IMM16;
527: }
528:
529: // 001111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
530: OP_DEF(lda_b_imm)
531: {
532: if (FLD_D == 0)
533: return;
534: rD = rS1 + IMM16;
535: }
536:
537: // 010000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
538: OP_DEF(and_imm)
539: {
540: if (FLD_D == 0)
541: return;
542: rD = rS1 & (IMM16 | 0xffff0000U);
543: }
544:
545: // 010001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
546: OP_DEF(and_u_imm)
547: {
548: if (FLD_D == 0)
549: return;
550: rD = rS1 & ((IMM16 << 16) | 0x0000ffffU);
551: }
552:
553: // 010010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
554: OP_DEF(mask_imm)
555: {
556: if (FLD_D == 0)
557: return;
558: rD = rS1 & IMM16;
559: }
560:
561: // 010011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
562: OP_DEF(mask_u_imm)
563: {
564: if (FLD_D == 0)
565: return;
566: rD = rS1 & (IMM16 << 16);
567: }
568:
569: // 010100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
570: OP_DEF(xor_imm)
571: {
572: if (FLD_D == 0)
573: return;
574: rD = rS1 ^ IMM16;
575: }
576:
577: // 010101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
578: OP_DEF(xor_u_imm)
579: {
580: if (FLD_D == 0)
581: return;
582: rD = rS1 ^ (IMM16 << 16);
583: }
584:
585: // 010110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
586: OP_DEF(or_imm)
587: {
588: if (FLD_D == 0)
589: return;
590: rD = rS1 | IMM16;
591: }
592:
593: // 010111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
594: OP_DEF(or_u_imm)
595: {
596: if (FLD_D == 0)
597: return;
598: rD = rS1 | (IMM16 << 16);
599: }
600:
601: // 011000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
602: OP_DEF(addu_imm)
603: {
604: if (FLD_D == 0)
605: return;
606: rD = rS1 + IMM16;
607: }
608:
609: // 011001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
610: OP_DEF(subu_imm)
611: {
612: if (FLD_D == 0)
613: return;
614: rD = rS1 - IMM16;
615: }
616:
617: // 011010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
618: OP_DEF(divu_imm)
619: {
620: if (!IsFPUEnable()) {
621: fpu_unimpl();
622: return;
623: }
624: if (IMM16 == 0) {
625: Exception(M88K_EXCEP_INT_DIV);
626: return;
627: }
628: if (FLD_D == 0)
629: return;
630: rD = rS1 / IMM16;
631: }
632:
633: // 011011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
634: OP_DEF(mul_imm)
635: {
636: if (!IsFPUEnable()) {
637: fpu_unimpl();
638: return;
639: }
640: if (FLD_D == 0)
641: return;
642: rD = rS1 * IMM16;
643: }
644:
645: // 011100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
646: OP_DEF(add_imm)
647: {
648: uint32 imm = IMM16;
649: uint32 res = rS1 + imm;
650: if (isovf_add(rS1, imm, res)) {
651: Exception(M88K_EXCEP_INT_OVF);
652: return;
653: }
654: if (FLD_D == 0)
655: return;
656: rD = res;
657: }
658:
659: // 011101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
660: OP_DEF(sub_imm)
661: {
662: uint32 imm = IMM16;
663: uint32 res = rS1 - imm;
664: if (isovf_sub(rS1, imm, res)) {
665: Exception(M88K_EXCEP_INT_OVF);
666: return;
667: }
668: if (FLD_D == 0)
669: return;
670: rD = res;
671: }
672:
673: // 011110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
674: OP_DEF(div_imm)
675: {
676: if (!IsFPUEnable()) {
677: fpu_unimpl();
678: return;
679: }
1.1.1.2 ! root 680: if ((int32)rS1 < 0 || IMM16 == 0) {
1.1 root 681: Exception(M88K_EXCEP_INT_DIV);
682: return;
683: }
684: if (FLD_D == 0)
685: return;
686: rD = rS1 / IMM16;
687: }
688:
689: // 011111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
690: OP_DEF(cmp_imm)
691: {
692: if (FLD_D == 0)
693: return;
694: rD = acc_cmp(rS1, IMM16);
695: }
696:
697: // 100000_DDDDDzzzzz_01000n_nnnnnzzzzz
698: OP_DEF(ldcr)
699: {
700: if (IsUser()) {
701: Exception(M88K_EXCEP_PRIV);
702: return;
703: }
704: if (FLD_CR > countof(cr)) {
705: // 88100 undocumented,
706: // 88110 compatible
707: Exception(M88K_EXCEP_UNIMPL_OP);
708: return;
709: }
710: if (FLD_D == 0)
711: return;
712: rD = cr[FLD_CR];
713: }
714:
715: // 100000_DDDDDzzzzz_01001n_nnnnnzzzzz
716: OP_DEF(fldcr)
717: {
718: int n = FLD_CR;
719:
720: if (IsUser()) {
721: // fcr62, 63 はユーザモードでアクセスできる
722: // それ以外はスーパバイザ用。
723: if (n < 62) {
724: Exception(M88K_EXCEP_PRIV);
725: return;
726: }
727: }
728:
729: if (8 < n && n < 62) {
730: // 未実装 FCR
731: // 88100 undocumented,
732: // 88110 compatible
733: Exception(M88K_EXCEP_UNIMPL_OP);
734: return;
735: }
736:
737: // fcr は 62,63 の配置に細工がしてある
738: if (n >= 62) {
739: n = n - 62 + 9;
740: }
741: if (FLD_D == 0)
742: return;
743: rD = fcr[n];
744: }
745:
746: // 100000_zzzzzSSSSS_10000n_nnnnnsssss
747: OP_DEF(stcr)
748: {
749: if (IsUser()) {
750: Exception(M88K_EXCEP_PRIV);
751: return;
752: }
753: if (FLD_CR > countof(cr)) {
754: // 88100 undocumented,
755: // 88110 unimpl_op
756: Exception(M88K_EXCEP_UNIMPL_OP);
757: return;
758: }
759: cr[FLD_CR] = rS1;
1.1.1.2 ! root 760: if (FLD_CR == 1) {
! 761: SetPSR(psr);
! 762: }
1.1 root 763: }
764:
765: // 100000_zzzzzSSSSS_10001n_nnnnnsssss
766: OP_DEF(fstcr)
767: {
768: int n = FLD_CR;
769:
770: if (IsUser()) {
771: // fcr62, 63 はユーザモードでアクセスできる
772: // それ以外はスーパバイザ用。
773: if (n < 62) {
774: Exception(M88K_EXCEP_PRIV);
775: return;
776: }
777: }
778:
779: if (8 < n && n < 62) {
780: // 未実装 FCR
781: // 88100 null op
782: // 88110 fpu-unimpl
783: return;
784: }
785:
786: // fcr は 62,63 の配置に細工がしてある
787: if (n >= 62) {
788: n = n - 62 + 9;
789: }
790: fcr[n] = rS1;
791: }
792:
793: // 100000_DDDDDSSSSS_11000n_nnnnnsssss
794: OP_DEF(xcr)
795: {
796: uint32 tmp;
797:
798: if (IsUser()) {
799: Exception(M88K_EXCEP_PRIV);
800: return;
801: }
802: if (FLD_CR > countof(cr)) {
803: // 88100 undocumented,
804: // 88110 unimpl_op
805: Exception(M88K_EXCEP_UNIMPL_OP);
806: return;
807: }
808: tmp = rS1;
809: rD = cr[FLD_CR];
810: cr[FLD_CR] = tmp;
1.1.1.2 ! root 811: if (FLD_CR == 1) {
! 812: SetPSR(psr);
! 813: }
1.1 root 814: r[0] = 0;
815: }
816:
817: // 100000_DDDDDSSSSS_11001n_nnnnnsssss
818: OP_DEF(fxcr)
819: {
820: uint32 tmp;
821: int n = FLD_CR;
822:
823: if (IsUser()) {
824: // fcr62, 63 はユーザモードでアクセスできる
825: // それ以外はスーパバイザ用。
826: if (n < 62) {
827: Exception(M88K_EXCEP_PRIV);
828: return;
829: }
830: }
831:
832: if (8 < n && n < 62) {
833: // 未実装 FCR
834: // 88100 null op
835: // 88110 fpu-unimpl
836: return;
837: }
838:
839: // fcr は 62,63 の配置に細工がしてある
840: if (n >= 62) {
841: n = n - 62 + 9;
842: }
843: tmp = rS1;
844: rD = fcr[n];
845: fcr[n] = tmp;
846: r[0] = 0;
847: }
848:
849: // 100001_DDDDDSSSSS_00000n_nnnnnsssss
850: OP_DEF(fmul)
851: {
852: OP_FUNC(unimpl);
853: }
854:
855: // 100001_DDDDD00000_001000_000nnsssss
856: OP_DEF(flt)
857: {
858: OP_FUNC(unimpl);
859: }
860:
861: // 100001_DDDDDSSSSS_00101n_nnnnnsssss
862: OP_DEF(fadd)
863: {
864: OP_FUNC(unimpl);
865: }
866:
867: // 100001_DDDDDSSSSS_00110n_nnnnnsssss
868: OP_DEF(fsub)
869: {
870: OP_FUNC(unimpl);
871: }
872:
873: // 100001_DDDDDSSSSS_00111n_nnnnnsssss
874: OP_DEF(fcmp)
875: {
876: OP_FUNC(unimpl);
877: }
878:
879: // 100001_DDDDD00000_010010_0nn00sssss
880: OP_DEF(int)
881: {
882: OP_FUNC(unimpl);
883: }
884:
885: // 100001_DDDDD00000_010100_0nn00sssss
886: OP_DEF(nint)
887: {
888: OP_FUNC(unimpl);
889: }
890:
891: // 100001_DDDDD00000_010110_0nn00sssss
892: OP_DEF(trnc)
893: {
894: OP_FUNC(unimpl);
895: }
896:
897: // 100001_DDDDDSSSSS_01110n_nnnnnsssss
898: OP_DEF(fdiv)
899: {
900: OP_FUNC(unimpl);
901: }
902:
903: // 110000_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
904: OP_DEF(br)
905: {
906: EnterBranch();
1.1.1.2 ! root 907: DoBranch(xip + D26);
1.1 root 908: ExitBranch();
909: }
910:
911: // 110001_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
912: OP_DEF(br_n)
913: {
914: EnterBranch();
1.1.1.2 ! root 915: DoBranch(xip + D26);
1.1 root 916: ExitDelayBranch();
917: }
918:
919: // 110010_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
920: OP_DEF(bsr)
921: {
922: EnterBranch();
1.1.1.2 ! root 923: DoBranch(xip + D26);
1.1 root 924: r[1] = nip;
925: ExitBranch();
926: }
927:
928: // 110011_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
929: OP_DEF(bsr_n)
930: {
931: EnterBranch();
1.1.1.2 ! root 932: DoBranch(xip + D26);
1.1 root 933: r[1] = nip + 4;
934: ExitDelayBranch();
935: }
936:
937: // 110100_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
938: OP_DEF(bb0)
939: {
940: if ((rS1 & (1 << B5)) == 0) {
941: EnterBranch();
1.1.1.2 ! root 942: DoBranch(xip + D16);
1.1 root 943: ExitBranch();
944: }
945: }
946:
947: // 110101_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
948: OP_DEF(bb0_n)
949: {
950: if ((rS1 & (1 << B5)) == 0) {
951: EnterBranch();
1.1.1.2 ! root 952: DoBranch(xip + D16);
1.1 root 953: ExitDelayBranch();
954: }
955: }
956:
957: // 110110_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
958: OP_DEF(bb1)
959: {
960: if ((rS1 & (1 << B5)) != 0) {
961: EnterBranch();
1.1.1.2 ! root 962: DoBranch(xip + D16);
1.1 root 963: ExitBranch();
964: }
965: }
966:
967: // 110111_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
968: OP_DEF(bb1_n)
969: {
970: if ((rS1 & (1 << B5)) != 0) {
971: EnterBranch();
1.1.1.2 ! root 972: DoBranch(xip + D16);
1.1 root 973: ExitDelayBranch();
974: }
975: }
976:
977: // 111010_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
978: OP_DEF(bcnd)
979: {
980: if (acc_cnd(rS1) & M5) {
981: EnterBranch();
1.1.1.2 ! root 982: DoBranch(xip + D16);
1.1 root 983: ExitBranch();
984: }
985: }
986:
987: // 111011_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
988: OP_DEF(bcnd_n)
989: {
990: if (acc_cnd(rS1) & M5) {
991: EnterBranch();
1.1.1.2 ! root 992: DoBranch(xip + D16);
1.1 root 993: ExitDelayBranch();
994: }
995: }
996:
997: // 111100_DDDDDSSSSS_100000_wwwwwooooo
998: OP_DEF(clr_1)
999: {
1000: if (FLD_D == 0)
1001: return;
1002: rD = rS1 & ~acc_bf(W5, O5);
1003: }
1004:
1005: // 111100_DDDDDSSSSS_100010_wwwwwooooo
1006: OP_DEF(set_1)
1007: {
1008: if (FLD_D == 0)
1009: return;
1010: rD = rS1 | acc_bf(W5, O5);
1011: }
1012:
1013: // 111100_DDDDDSSSSS_100100_wwwwwooooo
1014: OP_DEF(ext_1)
1015: {
1016: int w, o, left;
1017: uint32 tmp;
1018:
1019: if (FLD_D == 0)
1020: return;
1021: w = W5;
1022: if (w == 0)
1023: w = 32;
1024: o = O5;
1025: left = 32 - w - o;
1026: tmp = ASL(rS1, left);
1027: tmp = ASR(tmp, left);
1028: rD = ASR(tmp, o);
1029: }
1030:
1031: // 111100_DDDDDSSSSS_100110_wwwwwooooo
1032: OP_DEF(extu_1)
1033: {
1034: int w, o, left;
1035: uint32 tmp;
1036:
1037: if (FLD_D == 0)
1038: return;
1039: w = W5;
1040: if (w == 0)
1041: w = 32;
1042: o = O5;
1043: left = 32 - w - o;
1044: tmp = ASL(rS1, left);
1045: tmp = LSR(tmp, left);
1046: rD = tmp >> o;
1047: }
1048:
1049: // 111100_DDDDDSSSSS_101000_wwwwwooooo
1050: OP_DEF(mak_1)
1051: {
1052: if (FLD_D == 0)
1053: return;
1054: rD = (rS1 << O5) & acc_bf(W5, O5);
1055: }
1056:
1057: // 111100_DDDDDSSSSS_101010_zzzzzooooo
1058: OP_DEF(rot_1)
1059: {
1060: if (FLD_D == 0)
1061: return;
1062: rD = ROR(rS1, O5);
1063: }
1064:
1065: // 111100_bbbbbSSSSS_110100_0vvvvvvvvv
1066: OP_DEF(tb0)
1067: {
1068: if (IsUser() && VEC9 < 128) {
1069: Exception(M88K_EXCEP_PRIV);
1070: return;
1071: }
1072: if ((rS1 & (1 << B5)) == 0) {
1073: ExceptionCore(VEC9, ExceptionKind::TRAP);
1074: }
1075: }
1076:
1077: // 111100_bbbbbSSSSS_110110_0vvvvvvvvv
1078: OP_DEF(tb1)
1079: {
1080: if (IsUser() && VEC9 < 128) {
1081: Exception(M88K_EXCEP_PRIV);
1082: return;
1083: }
1084: if ((rS1 & (1 << B5)) != 0) {
1085: ExceptionCore(VEC9, ExceptionKind::TRAP);
1086: }
1087: }
1088:
1089: // 111100_MMMMMSSSSS_111010_0vvvvvvvvv
1090: OP_DEF(tcnd)
1091: {
1092: if (IsUser() && VEC9 < 128) {
1093: Exception(M88K_EXCEP_PRIV);
1094: return;
1095: }
1096: if (acc_cnd(rS1) & M5) {
1097: ExceptionCore(VEC9, ExceptionKind::TRAP);
1098: }
1099: }
1100:
1101: // 111101_DDDDDSSSSS_000000_xU000sssss
1102: OP_DEF(xmem_bu)
1103: {
1104: uint64 tmp;
1105: uint32 addr;
1106: uint32 usr;
1107:
1108: LDST_USR_SCALE_ALIGN(1);
1109:
1110: lastaddr = addr;
1.1.1.2 ! root 1111:
! 1112: // 例外安全のために都度 S/U ビットを制御
! 1113: if (__predict_false(usr)) cmmu[1].SetSuper(false);
! 1114: tmp = cmmu[1].xmem_8(addr, rD);
! 1115: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1116: if ((int64)tmp < 0) {
1.1.1.2 ! root 1117: XmemDataException(addr, rD, DM_BU | DM_LOCK | usr);
1.1 root 1118: return;
1119: }
1120: if (FLD_D == 0)
1121: return;
1122: rD = tmp;
1123: }
1124:
1125: // 111101_DDDDDSSSSS_000001_xU000sssss
1126: OP_DEF(xmem_w)
1127: {
1128: uint64 tmp;
1129: uint32 addr;
1130: uint32 usr;
1131:
1132: LDST_USR_SCALE_ALIGN(4);
1133:
1134: lastaddr = addr;
1.1.1.2 ! root 1135:
! 1136: // 例外安全のために都度 S/U ビットを制御
! 1137: if (__predict_false(usr)) cmmu[1].SetSuper(false);
! 1138: tmp = cmmu[1].xmem_32(addr, rD);
! 1139: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1140: if ((int64)tmp < 0) {
1.1.1.2 ! root 1141: XmemDataException(addr, rD, DM_W | DM_LOCK | usr);
1.1 root 1142: return;
1143: }
1.1.1.2 ! root 1144:
1.1 root 1145: if (FLD_D == 0)
1146: return;
1147: rD = tmp;
1148: }
1149:
1150: // 111101_DDDDDSSSSS_000010_xU000sssss
1151: OP_DEF(ld_hu)
1152: {
1153: uint64 tmp;
1154: uint32 addr;
1155: uint32 usr;
1156:
1157: LDST_USR_SCALE_ALIGN(2);
1158:
1159: lastaddr = addr;
1.1.1.2 ! root 1160:
! 1161: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1 root 1162: tmp = cmmu[1].load_16(addr);
1.1.1.2 ! root 1163: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1164:
1.1 root 1165: if ((int64)tmp < 0) {
1166: ReadDataException(addr, DM_HU | usr);
1167: return;
1168: }
1169: if (FLD_D == 0)
1170: return;
1171: rD = tmp;
1172: }
1173:
1174: // 111101_DDDDDSSSSS_000011_xU000sssss
1175: OP_DEF(ld_bu)
1176: {
1177: uint64 tmp;
1178: uint32 addr;
1179: uint32 usr;
1180:
1181: LDST_USR_SCALE_ALIGN(1);
1182:
1183: lastaddr = addr;
1.1.1.2 ! root 1184:
! 1185: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1 root 1186: tmp = cmmu[1].load_8(addr);
1.1.1.2 ! root 1187: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1188:
1.1 root 1189: if ((int64)tmp < 0) {
1190: ReadDataException(addr, DM_BU | usr);
1191: return;
1192: }
1193: if (FLD_D == 0)
1194: return;
1195: rD = tmp;
1196: }
1197:
1198: // 111101_DDDDDSSSSS_000100_xU000sssss
1199: OP_DEF(ld_d)
1200: {
1201: uint64 tmp, tmp2;
1202: uint32 addr;
1203: uint32 usr;
1204:
1205: LDST_USR_SCALE_ALIGN(8);
1206:
1207: lastaddr = addr;
1.1.1.2 ! root 1208:
! 1209: // 例外安全のために都度 S/U ビットを制御
! 1210: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1 root 1211: tmp = cmmu[1].load_32(addr);
1.1.1.2 ! root 1212: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1213:
1.1 root 1214: if ((int64)tmp < 0) {
1215: ReadDataException(addr, DM_D1 | usr);
1216: return;
1217: }
1218: addr += 4;
1.1.1.2 ! root 1219:
! 1220: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1 root 1221: tmp2 = cmmu[1].load_32(addr);
1.1.1.2 ! root 1222: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1223:
1.1 root 1224: if ((int64)tmp < 0) {
1225: ReadDataException(addr, DM_D2 | usr);
1226: return;
1227: }
1228: rD = tmp;
1229: r[(FLD_D + 1) & 0x1f] = tmp2;
1230: r[0] = 0;
1231: }
1232:
1233: // 111101_DDDDDSSSSS_000101_xU000sssss
1234: OP_DEF(ld_w)
1235: {
1236: uint64 tmp;
1237: uint32 addr;
1238: uint32 usr;
1239:
1240: LDST_USR_SCALE_ALIGN(4);
1241:
1242: lastaddr = addr;
1.1.1.2 ! root 1243:
! 1244: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1 root 1245: tmp = cmmu[1].load_32(addr);
1.1.1.2 ! root 1246: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1247:
1.1 root 1248: if ((int64)tmp < 0) {
1249: ReadDataException(addr, DM_W | usr);
1250: return;
1251: }
1252: if (FLD_D == 0)
1253: return;
1254: rD = tmp;
1255: }
1256:
1257: // 111101_DDDDDSSSSS_000110_xU000sssss
1258: OP_DEF(ld_h)
1259: {
1260: uint64 tmp;
1261: uint32 addr;
1262: uint32 usr;
1263:
1264: LDST_USR_SCALE_ALIGN(2);
1265:
1266: lastaddr = addr;
1.1.1.2 ! root 1267:
! 1268: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1 root 1269: tmp = cmmu[1].load_16(addr);
1.1.1.2 ! root 1270: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1271:
1.1 root 1272: if ((int64)tmp < 0) {
1273: ReadDataException(addr, DM_H | usr);
1274: return;
1275: }
1276: if (FLD_D == 0)
1277: return;
1278: rD = (uint32)(int32)(int16)tmp;
1279: }
1280:
1281: // 111101_DDDDDSSSSS_000111_xU000sssss
1282: OP_DEF(ld_b)
1283: {
1284: uint64 tmp;
1285: uint32 addr;
1286: uint32 usr;
1287:
1288: LDST_USR_SCALE_ALIGN(1);
1289:
1290: lastaddr = addr;
1.1.1.2 ! root 1291:
! 1292: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1 root 1293: tmp = cmmu[1].load_8(addr);
1.1.1.2 ! root 1294: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1295:
1.1 root 1296: if ((int64)tmp < 0) {
1297: ReadDataException(addr, DM_B | usr);
1298: return;
1299: }
1300: if (FLD_D == 0)
1301: return;
1302: rD = (uint32)(int32)(int8)tmp;
1303: }
1304:
1305: // 111101_DDDDDSSSSS_001000_xU000sssss
1306: OP_DEF(st_d)
1307: {
1.1.1.2 ! root 1308: uint64 tmp2;
1.1 root 1309: uint32 addr;
1310: uint32 usr;
1311:
1312: LDST_USR_SCALE_ALIGN(8);
1313:
1314: lastaddr = addr;
1.1.1.2 ! root 1315:
! 1316: if (__predict_false(usr)) cmmu[1].SetSuper(false);
! 1317: tmp2 = cmmu[1].store_32(addr, rD);
! 1318: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1319:
! 1320: if ((int64)tmp2 < 0) {
1.1 root 1321: WriteDataException(addr, rD, DM_D1 | usr);
1322: return;
1323: }
1.1.1.2 ! root 1324:
1.1 root 1325: addr += 4;
1.1.1.2 ! root 1326:
! 1327: if (__predict_false(usr)) cmmu[1].SetSuper(false);
! 1328: tmp2 = cmmu[1].store_32(addr, r[(FLD_D + 1) & 0x1f]);
! 1329: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1330:
! 1331: if ((int64)tmp2 < 0) {
1.1 root 1332: WriteDataException(addr, r[(FLD_D + 1) & 0x1f], DM_D2 | usr);
1333: return;
1334: }
1335: }
1336:
1337: // 111101_DDDDDSSSSS_001001_xU000sssss
1338: OP_DEF(st_w)
1339: {
1.1.1.2 ! root 1340: uint64 tmp2;
1.1 root 1341: uint32 addr;
1342: uint32 usr;
1343:
1344: LDST_USR_SCALE_ALIGN(4);
1345:
1346: lastaddr = addr;
1.1.1.2 ! root 1347:
! 1348: if (__predict_false(usr)) cmmu[1].SetSuper(false);
! 1349: tmp2 = cmmu[1].store_32(addr, rD);
! 1350: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1351:
! 1352: if ((int64)tmp2 < 0) {
1.1 root 1353: WriteDataException(addr, rD, DM_W | usr);
1354: return;
1355: }
1356: }
1357:
1358: // 111101_DDDDDSSSSS_001010_xU000sssss
1359: OP_DEF(st_h)
1360: {
1.1.1.2 ! root 1361: uint64 tmp2;
1.1 root 1362: uint32 addr;
1363: uint32 usr;
1364:
1365: LDST_USR_SCALE_ALIGN(2);
1366:
1367: lastaddr = addr;
1.1.1.2 ! root 1368:
! 1369: if (__predict_false(usr)) cmmu[1].SetSuper(false);
! 1370: tmp2 = cmmu[1].store_16(addr, rD);
! 1371: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1372:
! 1373: if ((int64)tmp2 < 0) {
1.1 root 1374: WriteDataException(addr, rD, DM_H | usr);
1375: return;
1376: }
1377: }
1378:
1379: // 111101_DDDDDSSSSS_001011_xU000sssss
1380: OP_DEF(st_b)
1381: {
1.1.1.2 ! root 1382: uint64 tmp2;
1.1 root 1383: uint32 addr;
1384: uint32 usr;
1385:
1386: LDST_USR_SCALE_ALIGN(1);
1387:
1388: lastaddr = addr;
1.1.1.2 ! root 1389:
! 1390: if (__predict_false(usr)) cmmu[1].SetSuper(false);
! 1391: tmp2 = cmmu[1].store_8(addr, rD);
! 1392: if (__predict_false(usr)) cmmu[1].SetSuper(true);
! 1393:
! 1394: if ((int64)tmp2 < 0) {
1.1 root 1395: WriteDataException(addr, rD, DM_B | usr);
1396: return;
1397: }
1398: }
1399:
1400: // 111101_DDDDDSSSSS_001100_xU000sssss
1401: OP_DEF(lda_d)
1402: {
1403: uint32 addr;
1404: uint32 usr;
1405:
1406: LDST_USR_SCALE(8);
1407:
1408: if (FLD_D == 0)
1409: return;
1410: rD = addr;
1411: }
1412:
1413: // 111101_DDDDDSSSSS_001101_xU000sssss
1414: OP_DEF(lda_w)
1415: {
1416: uint32 addr;
1417: uint32 usr;
1418:
1419: LDST_USR_SCALE(4);
1420:
1421: if (FLD_D == 0)
1422: return;
1423: rD = addr;
1424: }
1425:
1426: // 111101_DDDDDSSSSS_001110_xU000sssss
1427: OP_DEF(lda_h)
1428: {
1429: uint32 addr;
1430: uint32 usr;
1431:
1432: LDST_USR_SCALE(2);
1433:
1434: if (FLD_D == 0)
1435: return;
1436: rD = addr;
1437: }
1438:
1439: // 111101_DDDDDSSSSS_001111_xU000sssss
1440: OP_DEF(lda_b)
1441: {
1442: uint32 addr;
1443: uint32 usr;
1444:
1445: LDST_USR_SCALE(1);
1446:
1447: if (FLD_D == 0)
1448: return;
1449: rD = addr;
1450: }
1451:
1452: // 111101_DDDDDSSSSS_010000_00000sssss
1453: OP_DEF(and)
1454: {
1455: if (FLD_D == 0)
1456: return;
1457: rD = rS1 & rS2;
1458: }
1459:
1460: // 111101_DDDDDSSSSS_010001_00000sssss
1461: OP_DEF(and_c)
1462: {
1463: if (FLD_D == 0)
1464: return;
1465: rD = rS1 & ~rS2;
1466: }
1467:
1468: // 111101_DDDDDSSSSS_010100_00000sssss
1469: OP_DEF(xor)
1470: {
1471: if (FLD_D == 0)
1472: return;
1473: rD = rS1 ^ rS2;
1474: }
1475:
1476: // 111101_DDDDDSSSSS_010101_00000sssss
1477: OP_DEF(xor_c)
1478: {
1479: if (FLD_D == 0)
1480: return;
1481: rD = rS1 ^ ~rS2;
1482: }
1483:
1484: // 111101_DDDDDSSSSS_010110_00000sssss
1485: OP_DEF(or)
1486: {
1.1.1.2 ! root 1487: if (FLD_D == 0) {
! 1488: nop_counter++;
1.1 root 1489: return;
1.1.1.2 ! root 1490: }
1.1 root 1491: rD = rS1 | rS2;
1492: }
1493:
1494: // 111101_DDDDDSSSSS_010111_00000sssss
1495: OP_DEF(or_c)
1496: {
1497: if (FLD_D == 0)
1498: return;
1499: rD = rS1 | ~rS2;
1500: }
1501:
1502: // 111101_DDDDDSSSSS_011000_nn000sssss
1503: OP_DEF(addu)
1504: {
1.1.1.2 ! root 1505: uint64 res = (uint64)rS1 + rS2;
1.1 root 1506: if (IsCI) {
1507: res += GetCY();
1508: }
1509: if (IsCO) {
1510: SetCY((res >> 32) & 1);
1511: }
1512: if (FLD_D == 0)
1513: return;
1514: rD = res;
1515: }
1516:
1517: // 111101_DDDDDSSSSS_011001_nn000sssss
1518: OP_DEF(subu)
1519: {
1.1.1.2 ! root 1520: // sub 命令では CY ビットは Z80 とかと逆で、0 ならボロー発生。
! 1521: // 88100 のマニュアルには書いてない。88110 のマニュアルにある。
! 1522:
! 1523: // 1 の補数をとって足す。
! 1524: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1525: if (IsCI) {
1.1.1.2 ! root 1526: res += GetCY();
! 1527: } else {
! 1528: res += 1;
1.1 root 1529: }
1530: if (IsCO) {
1531: SetCY((res >> 32) & 1);
1532: }
1533: if (FLD_D == 0)
1534: return;
1535: rD = res;
1536: }
1537:
1538: // 111101_DDDDDSSSSS_011010_zz000sssss
1539: OP_DEF(divu)
1540: {
1541: if (!IsFPUEnable()) {
1542: fpu_unimpl();
1543: return;
1544: }
1545: if (rS2 == 0) {
1546: Exception(M88K_EXCEP_INT_DIV);
1547: return;
1548: }
1549: if (FLD_D == 0)
1550: return;
1551: rD = rS1 / rS2;
1552: }
1553:
1554: // 111101_DDDDDSSSSS_011011_zz000sssss
1555: OP_DEF(mul)
1556: {
1557: if (!IsFPUEnable()) {
1558: fpu_unimpl();
1559: return;
1560: }
1561: if (FLD_D == 0)
1562: return;
1563: rD = rS1 * rS2;
1564: }
1565:
1566: // 111101_DDDDDSSSSS_011100_nn000sssss
1567: OP_DEF(add)
1568: {
1.1.1.2 ! root 1569: uint64 res = (uint64)rS1 + rS2;
1.1 root 1570: if (IsCI) {
1571: res += GetCY();
1572: }
1573: // XXX: オーバーフローが起きたときにキャリーが更新されるかどうか
1574: // ドキュメントされてない気がする
1575: if (IsCO) {
1576: SetCY((res >> 32) & 1);
1577: }
1578: if (isovf_add(rS1, rS2, res)) {
1579: Exception(M88K_EXCEP_INT_OVF);
1580: return;
1581: }
1582: if (FLD_D == 0)
1583: return;
1584: rD = res;
1585: }
1586:
1587: // 111101_DDDDDSSSSS_011101_nn000sssss
1588: OP_DEF(sub)
1589: {
1.1.1.2 ! root 1590: // sub 命令では CY ビットは Z80 とかと逆で、0 ならボロー発生。
! 1591: // 88100 のマニュアルには書いてない。88110 のマニュアルにある。
! 1592:
! 1593: // 1 の補数をとって足す。
! 1594: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1595: if (IsCI) {
1.1.1.2 ! root 1596: res += GetCY();
! 1597: } else {
! 1598: res += 1;
1.1 root 1599: }
1600: // XXX: オーバーフローが起きたときにキャリーが更新されるかどうか
1601: // ドキュメントされてない気がする
1602: if (IsCO) {
1603: SetCY((res >> 32) & 1);
1604: }
1605: if (isovf_sub(rS1, rS2, res)) {
1606: Exception(M88K_EXCEP_INT_OVF);
1607: return;
1608: }
1609: if (FLD_D == 0)
1610: return;
1611: rD = res;
1612: }
1613:
1614: // 111101_DDDDDSSSSS_011110_zz000sssss
1615: OP_DEF(div)
1616: {
1617: if (!IsFPUEnable()) {
1618: fpu_unimpl();
1619: return;
1620: }
1.1.1.2 ! root 1621: if ((int32)rS1 < 0 || (int32)rS2 <= 0) {
1.1 root 1622: Exception(M88K_EXCEP_INT_DIV);
1623: return;
1624: }
1625: if (FLD_D == 0)
1626: return;
1627: rD = rS1 / rS2;
1628: }
1629:
1630: // 111101_DDDDDSSSSS_011111_zz000sssss
1631: OP_DEF(cmp)
1632: {
1633: if (FLD_D == 0)
1634: return;
1635: rD = acc_cmp(rS1, rS2);
1636: }
1637:
1638: // 111101_DDDDDSSSSS_100000_00000sssss
1639: OP_DEF(clr_2)
1640: {
1641: if (FLD_D == 0)
1642: return;
1643: rD = rS1 & ~acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1644: }
1645:
1646: // 111101_DDDDDSSSSS_100010_00000sssss
1647: OP_DEF(set_2)
1648: {
1649: if (FLD_D == 0)
1650: return;
1651: rD = rS1 | acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1652: }
1653:
1654: // 111101_DDDDDSSSSS_100100_00000sssss
1655: OP_DEF(ext_2)
1656: {
1657: int w, o, left;
1658: uint32 tmp;
1659:
1660: if (FLD_D == 0)
1661: return;
1662: w = (rS2 >> 5) & 0x1f;
1663: if (w == 0)
1664: w = 32;
1665: o = (rS2 ) & 0x1f;
1666: left = 32 - w - o;
1667: tmp = ASL(rS1, left);
1668: tmp = ASR(tmp, left);
1669: rD = ASR(tmp, o);
1670: }
1671:
1672: // 111101_DDDDDSSSSS_100110_00000sssss
1673: OP_DEF(extu_2)
1674: {
1675: int w, o, left;
1676: uint32 tmp;
1677:
1678: if (FLD_D == 0)
1679: return;
1680: w = (rS2 >> 5) & 0x1f;
1681: if (w == 0)
1682: w = 32;
1683: o = (rS2 ) & 0x1f;
1684: left = 32 - w - o;
1685: tmp = ASL(rS1, left);
1686: tmp = LSR(tmp, left);
1687: rD = tmp >> o;
1688: }
1689:
1690: // 111101_DDDDDSSSSS_101000_00000sssss
1691: OP_DEF(mak_2)
1692: {
1693: if (FLD_D == 0)
1694: return;
1695: int w = (rS2 >> 5) & 0x1f;
1696: int o = (rS2 ) & 0x1f;
1697: rD = (rS1 << o) & acc_bf(w, o);
1698: }
1699:
1700: // 111101_DDDDDSSSSS_101010_00000sssss
1701: OP_DEF(rot_2)
1702: {
1703: if (FLD_D == 0)
1704: return;
1705: int o = (rS2 ) & 0x1f;
1706: rD = ROR(rS1, o);
1707: }
1708:
1709: // 111101_zzzzzzzzzz_110000_00000sssss
1710: OP_DEF(jmp)
1711: {
1712: EnterBranch();
1.1.1.2 ! root 1713: DoBranch(rS2);
1.1 root 1714: ExitBranch();
1715: }
1716:
1717: // 111101_zzzzzzzzzz_110001_00000sssss
1718: OP_DEF(jmp_n)
1719: {
1720: EnterBranch();
1.1.1.2 ! root 1721: DoBranch(rS2);
1.1 root 1722: ExitDelayBranch();
1723: }
1724:
1725: // 111101_zzzzzzzzzz_110010_00000sssss
1726: OP_DEF(jsr)
1727: {
1728: EnterBranch();
1.1.1.2 ! root 1729: DoBranch(rS2);
1.1 root 1730: r[1] = nip;
1731: ExitBranch();
1732: }
1733:
1734: // 111101_zzzzzzzzzz_110011_00000sssss
1735: OP_DEF(jsr_n)
1736: {
1737: EnterBranch();
1.1.1.2 ! root 1738: DoBranch(rS2);
1.1 root 1739: r[1] = nip + 4;
1740: ExitDelayBranch();
1741: }
1742:
1.1.1.2 ! root 1743: // 111101_DDDDDzzzzz_111010_00000sssss
! 1744: OP_DEF(ff1)
! 1745: {
! 1746: int i;
! 1747: uint32 m = 0x80000000U;
! 1748:
! 1749: if (FLD_D == 0)
! 1750: return;
! 1751:
! 1752: if (rS2 == 0) {
! 1753: rD = 32;
! 1754: } else {
! 1755: for (i = 31; i >= 0; i--, m >>= 1) {
! 1756: if ((rS2 & m) != 0) {
! 1757: break;
! 1758: }
! 1759: }
! 1760: rD = i;
! 1761: }
! 1762:
! 1763: }
! 1764:
! 1765: // 111101_DDDDDzzzzz_111011_00000sssss
! 1766: OP_DEF(ff0)
! 1767: {
! 1768: int i;
! 1769: uint32 m = 0x80000000U;
! 1770:
! 1771: if (FLD_D == 0)
! 1772: return;
! 1773:
! 1774: if (rS2 == 0xffffffffU) {
! 1775: rD = 32;
! 1776: } else {
! 1777: for (i = 31; i >= 0; i--, m >>= 1) {
! 1778: if ((rS2 & m) == 0) {
! 1779: break;
! 1780: }
! 1781: }
! 1782: rD = i;
! 1783: }
! 1784: }
! 1785:
1.1 root 1786: // 111101_zzzzzzzzzz_111111_0000000000
1787: OP_DEF(rte)
1788: {
1.1.1.2 ! root 1789: SetPSR(epsr);
1.1 root 1790:
1.1.1.2 ! root 1791: // LUNA88K の ROM1.2 は sxip, snip, sfip を制御してくる。
! 1792: // ROM1.2 の DAE ハンドラは、
! 1793: // sxip = INVALID
! 1794: // snip = 0 (INVALID)
! 1795: // sfip = original sxip
! 1796: // で rte してくる。
! 1797: // CPU は sxip は評価しない。snip は 0 なので、無効として nop 扱い。
! 1798: // (実際はクロックが消費されるかも?)
! 1799: // sfip が VALID なので、そこから実行を再開する。
! 1800: if (snip & SIP_V) {
! 1801: DoBranch(snip & SIP_MASK);
! 1802: fetch();
! 1803: fip = sfip & SIP_MASK;
! 1804: } else {
! 1805: DoBranch(sfip & SIP_MASK);
! 1806: fetch();
! 1807: }
1.1 root 1808:
1809: // ディレイスロットにいた命令かどうかをやんわり復元する。
1810: // 88110 ではこの情報が E?IP に保持されているが
1811: // 88100 にはない。
1812: if (nip + 4 != fip) {
1813: opF = OpSetDelay(opF);
1814: }
1815: }
1816:
1817: // 111101_zzzzzSSSSS_111110_00000SSSSS
1818: OP_DEF(tbnd_1)
1819: {
1820: if (rS1 > rS2) {
1821: Exception(M88K_EXCEP_BOUNDS);
1822: }
1823: }
1824:
1825: // 111110_zzzzzSSSSS_nnnnnn_nnnnnnnnnn
1826: OP_DEF(tbnd_2)
1827: {
1828: if (rS1 > IMM16) {
1829: Exception(M88K_EXCEP_BOUNDS);
1830: }
1831: }
1832:
1833: // 111111_zzzzzzzzzz_000011_zzzzzzzzzz
1834: OP_DEF(getc)
1835: {
1836: printf("getc inst\n");
1837: int c = getchar();
1838: r[2] = c;
1839: }
1840:
1841: // 111111_zzzzzzzzzz_000100_zzzzzzzzzz
1842: OP_DEF(putc)
1843: {
1844: // r3 を表示
1845: putchar(r[3]);
1846: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.