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