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