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