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