|
|
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.3 ! root 7: #include "mpu680x0.h"
1.1 root 8: #include "m68030acc.h"
9:
1.1.1.3 ! root 10: /*static*/ inline uint32
! 11: m68030acc::vflag_add_8(uint32 src, uint32 dst, uint32 res)
! 12: {
! 13: return vflag_add_32(src, dst, res) << 24;
! 14: }
! 15:
! 16: /*static*/ inline uint32
! 17: m68030acc::vflag_add_16(uint32 src, uint32 dst, uint32 res)
! 18: {
! 19: return vflag_add_32(src, dst, res) << 16;
! 20: }
! 21:
! 22: /*static*/ inline uint32
! 23: m68030acc::vflag_add_32(uint32 src, uint32 dst, uint32 res)
! 24: {
! 25: return (src ^ res) & (dst ^ res);
! 26: }
! 27:
! 28: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
! 29: // src, dst の上位ビットはクリアしておくこと。
! 30: // 戻り値の上位ビットはクリアされている。
! 31: uint32
! 32: m68030acc::add_8(uint32 src, uint32 dst)
! 33: {
! 34: Z = dst + src;
! 35: C = Z >> 8;
! 36: X = C;
! 37: N = Z << 24;
! 38: Z &= 0xff;
! 39: V = vflag_add_8(src, dst, Z);
! 40: return Z;
! 41: }
! 42:
! 43: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
! 44: // src, dst の上位ビットはクリアしておくこと。
! 45: // 戻り値の上位ビットはクリアされている。
! 46: uint32
! 47: m68030acc::add_16(uint32 src, uint32 dst)
! 48: {
! 49: Z = dst + src;
! 50: C = Z >> 16;
! 51: X = C;
! 52: N = Z << 16;
! 53: Z &= 0xffff;
! 54: V = vflag_add_16(src, dst, Z);
! 55: return Z;
! 56: }
! 57:
! 58: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
! 59: uint32
! 60: m68030acc::add_32(uint32 src, uint32 dst)
! 61: {
! 62: CZ = (uint64)dst + (uint64)src;
! 63: X = C;
! 64: V = vflag_add_32(src, dst, Z);
! 65: N = Z;
! 66: return Z;
! 67: }
! 68:
! 69: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
! 70: // src, dst の上位ビットはクリアしておくこと。
! 71: // 戻り値の上位ビットはクリアされている。
! 72: uint32
! 73: m68030acc::addx_8(uint32 src, uint32 dst)
! 74: {
! 75: uint32 res = dst + src + (IsX() ? 1 : 0);
! 76: C = res >> 8;
! 77: X = C;
! 78: N = res << 24;
! 79: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
! 80: if (N != 0) {
! 81: Z = N;
! 82: }
! 83: V = vflag_add_8(src, dst, res);
! 84: return res & 0xff;
! 85: }
! 86:
! 87: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
! 88: // src, dst の上位ビットはクリアしておくこと。
! 89: // 戻り値の上位ビットはクリアされている。
! 90: uint32
! 91: m68030acc::addx_16(uint32 src, uint32 dst)
! 92: {
! 93: uint32 res = dst + src + (IsX() ? 1 : 0);
! 94: C = res >> 16;
! 95: X = C;
! 96: N = res << 16;
! 97: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
! 98: if (N != 0) {
! 99: Z = N;
! 100: }
! 101: V = vflag_add_16(src, dst, res);
! 102: return res & 0xffff;
! 103: }
! 104:
! 105: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
! 106: uint32
! 107: m68030acc::addx_32(uint32 src, uint32 dst)
! 108: {
! 109: uint64 res = (uint64)dst + (uint64)src + (IsX() ? 1 : 0);
! 110: C = res >> 32;
! 111: X = C;
! 112: N = res;
! 113: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
! 114: if (N != 0) {
! 115: Z = N;
! 116: }
! 117: V = vflag_add_32(src, dst, res);
! 118: return res;
! 119: }
! 120:
! 121:
! 122: /*static*/ inline uint32
! 123: m68030acc::vflag_sub_8(uint32 src, uint32 dst, uint32 res)
! 124: {
! 125: return vflag_sub_32(src, dst, res) << 24;
! 126: }
! 127:
! 128: /*static*/ inline uint32
! 129: m68030acc::vflag_sub_16(uint32 src, uint32 dst, uint32 res)
! 130: {
! 131: return vflag_sub_32(src, dst, res) << 16;
! 132: }
! 133:
! 134: /*static*/ inline uint32
! 135: m68030acc::vflag_sub_32(uint32 src, uint32 dst, uint32 res)
! 136: {
! 137: return (src ^ dst) & (dst ^ res);
! 138: }
! 139:
! 140: // dst - src を計算し、NZVC フラグをセットして結果を返す。
! 141: // src, dst の上位ビットはクリアしておくこと。
! 142: // 戻り値の上位ビットはクリアされている。
! 143: uint32
! 144: m68030acc::cmp_8(uint32 src, uint32 dst)
! 145: {
! 146: Z = dst - src;
! 147: C = Z >> 8;
! 148: N = Z << 24;
! 149: Z &= 0xff;
! 150: V = vflag_sub_8(src, dst, Z);
! 151: return Z;
! 152: }
! 153:
! 154: // dst - src を計算し、NZVC フラグをセットして結果を返す。
! 155: // src, dst の上位ビットはクリアしておくこと。
! 156: // 戻り値の上位ビットはクリアされている。
! 157: uint32
! 158: m68030acc::cmp_16(uint32 src, uint32 dst)
! 159: {
! 160: Z = dst - src;
! 161: C = Z >> 16;
! 162: N = Z << 16;
! 163: Z &= 0xffff;
! 164: V = vflag_sub_16(src, dst, Z);
! 165: return Z;
! 166: }
1.1 root 167:
1.1.1.3 ! root 168: // dst - src を計算し、NZVC フラグをセットして結果を返す。
! 169: uint32
! 170: m68030acc::cmp_32(uint32 src, uint32 dst)
! 171: {
! 172: CZ = (uint64)dst - (uint64)src;
! 173: N = Z;
! 174: V = vflag_sub_32(src, dst, Z);
! 175: return Z;
! 176: }
1.1 root 177:
1.1.1.3 ! root 178: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
! 179: // src, dst の上位ビットはクリアしておくこと。
! 180: // 戻り値の上位ビットはクリアされている。
! 181: uint32
! 182: m68030acc::sub_8(uint32 src, uint32 dst)
! 183: {
! 184: uint32 res = cmp_8(src, dst);
! 185: X = C;
! 186: return res;
! 187: }
1.1 root 188:
1.1.1.3 ! root 189: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
! 190: // src, dst の上位ビットはクリアしておくこと。
! 191: // 戻り値の上位ビットはクリアされている。
! 192: uint32
! 193: m68030acc::sub_16(uint32 src, uint32 dst)
1.1 root 194: {
1.1.1.3 ! root 195: uint32 res = cmp_16(src, dst);
! 196: X = C;
! 197: return res;
! 198: }
1.1 root 199:
1.1.1.3 ! root 200: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
! 201: uint32
! 202: m68030acc::sub_32(uint32 src, uint32 dst)
! 203: {
! 204: uint32 res = cmp_32(src, dst);
! 205: X = C;
! 206: return res;
! 207: }
1.1 root 208:
1.1.1.3 ! root 209: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
! 210: // src, dst の上位ビットはクリアしておくこと。
! 211: // 戻り値 res の上位ビットはクリアされている。
! 212: uint32
! 213: m68030acc::subx_8(uint32 src, uint32 dst)
! 214: {
! 215: uint32 res = dst - src - (IsX() ? 1 : 0);
! 216: C = res >> 8;
! 217: X = C;
! 218: N = res << 24;
! 219: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
! 220: if (N != 0) {
! 221: Z = N;
! 222: }
! 223: V = vflag_sub_8(src, dst, res);
! 224: return res & 0xff;
! 225: }
! 226:
! 227: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
! 228: // src, dst の上位ビットはクリアしておくこと。
! 229: // 戻り値 res の上位ビットはクリアされている。
! 230: uint32
! 231: m68030acc::subx_16(uint32 src, uint32 dst)
! 232: {
! 233: uint32 res = dst - src - (IsX() ? 1 : 0);
! 234: C = res >> 16;
! 235: X = C;
! 236: N = res << 16;
! 237: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
! 238: if (N != 0) {
! 239: Z = N;
! 240: }
! 241: V = vflag_sub_16(src, dst, res);
! 242: return res & 0xffff;
! 243: }
! 244:
! 245: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
! 246: uint32
! 247: m68030acc::subx_32(uint32 src, uint32 dst)
! 248: {
! 249: uint64 res = (uint64)dst - (uint64)src - (IsX() ? 1 : 0);
! 250: C = res >> 32;
! 251: X = C;
! 252: N = res;
! 253: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
! 254: if (N != 0) {
! 255: Z = N;
! 256: }
! 257: V = vflag_sub_32(src, dst, res);
! 258: return res;
! 259: }
! 260:
! 261: // src(u16) * dst(u16) を計算し、NZVC フラグをセットして結果(u32)を返す。
! 262: // src, dst の上位ビットはクリアしておくこと。
! 263: uint32
! 264: m68030acc::mulu_16(uint32 src, uint32 dst)
! 265: {
! 266: uint32 res = src * dst;
! 267: // 16x16->32 ではオーバーフローは起きないので move でよい
! 268: move_32(res);
! 269: return res;
! 270: }
! 271:
! 272: // src(s16) * dst(s16) を計算し、NZVC フラグをセットして結果(u32)を返す。
! 273: // src, dst の上位ビットはクリアしておくこと。
! 274: uint32
! 275: m68030acc::muls_16(uint32 src, uint32 dst)
! 276: {
! 277: int32 res = (int32)(int16)src * (int32)(int16)dst;
! 278: // 16x16->32 ではオーバーフローは起きないので move でよい
! 279: move_32(res);
! 280: return res;
! 281: }
! 282:
! 283: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
! 284: uint32
! 285: m68030acc::mulu_32(uint32 src, uint32 dst)
! 286: {
! 287: uint64 res = (uint64)src * (uint64)dst;
! 288: Z = res;
! 289: N = res;
! 290: C = 0;
! 291: if (res > 0xffffffffUL) {
! 292: V = V_BIT;
1.1 root 293: } else {
1.1.1.3 ! root 294: V = 0;
1.1 root 295: }
1.1.1.3 ! root 296: return (uint32)res;
! 297: }
1.1 root 298:
1.1.1.3 ! root 299: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
! 300: uint32
! 301: m68030acc::muls_32(uint32 src, uint32 dst)
! 302: {
! 303: int64 res = (int64)(int32)src * (int64)(int32)dst;
! 304: Z = res;
! 305: N = res;
! 306: C = 0;
! 307: // V フラグは64ビット演算結果の上位32ビットが
! 308: // 下位32ビットの符号拡張になっていなかった場合に立つ。
! 309: // つまり符号付き整数で 32bit 表現と 64bit 表現が一致していなければ立つ。
! 310: int32 tmp = res;
! 311: if (res != tmp) {
! 312: V = V_BIT;
! 313: } else {
! 314: V = 0;
1.1 root 315: }
1.1.1.3 ! root 316: return (uint32)res;
1.1 root 317: }
318:
1.1.1.3 ! root 319: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
! 320: uint64
! 321: m68030acc::mulu_64(uint32 src, uint32 dst)
1.1 root 322: {
1.1.1.3 ! root 323: uint64 res = (uint64)src * (uint64)dst;
! 324: N = res >> 32;
! 325: Z = N | res;
! 326: V = 0;
! 327: C = 0;
! 328: return res;
! 329: }
! 330:
! 331: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
! 332: uint64
! 333: m68030acc::muls_64(uint32 src, uint32 dst)
! 334: {
! 335: int64 res = (int64)(int32)src * (int64)(int32)dst;
! 336: N = res >> 32;
! 337: Z = N | res;
! 338: V = 0;
! 339: C = 0;
! 340: return res;
1.1 root 341: }
342:
343: void
1.1.1.3 ! root 344: m68030acc::btst(uint32 data, int n)
1.1 root 345: {
1.1.1.3 ! root 346: Z = data & (1 << n);
! 347: }
! 348:
! 349: uint32
! 350: m68030acc::bchg(uint32 data, int n)
! 351: {
! 352: Z = data & (1 << n);
! 353: data ^= (1 << n);
! 354: return data;
! 355: }
! 356:
! 357: uint32
! 358: m68030acc::bclr(uint32 data, int n)
! 359: {
! 360: Z = data & (1 << n);
! 361: data &= ~(1 << n);
! 362: return data;
! 363: }
! 364:
! 365: uint32
! 366: m68030acc::bset(uint32 data, int n)
! 367: {
! 368: Z = data & (1 << n);
! 369: data |= (1 << n);
! 370: return data;
! 371: }
! 372:
! 373:
! 374: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
! 375: // count は 0..63。data の上位はクリアしておくこと。
! 376: uint32
! 377: m68030acc::asl_8(uint32 data, int count)
! 378: {
! 379: if (count == 0) {
! 380: move_8(data);
! 381: return data;
! 382: }
! 383: int64 tmps = (int64)(int8)data;
! 384: if (count > 8) count = 9;
! 385: uint64 tmp = (uint64)tmps << count;
! 386: X = C = tmp >> 8;
! 387: N = tmp << 24;
! 388: Z = N;
! 389: // 送り出された全てのビットが元の MSB と一致すれば V=0
! 390: SetV(((int64)tmp >> 7) != (tmps >> 8));
! 391: return tmp & 0xff;
! 392: }
! 393:
! 394: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
! 395: // count は 0..63。data の上位はクリアしておくこと。
! 396: uint32
! 397: m68030acc::asl_16(uint32 data, int count)
! 398: {
! 399: if (count == 0) {
! 400: move_16(data);
! 401: return data;
! 402: }
! 403: int64 tmps = (int64)(int16)data;
! 404: if (count > 16) count = 17;
! 405: uint64 tmp = (uint64)tmps << count;
! 406: X = C = tmp >> 16;
! 407: N = tmp << 16;
! 408: Z = N;
! 409: // 送り出された全てのビットが元の MSB と一致すれば V=0
! 410: SetV(((int64)tmp >> 15) != (tmps >> 16));
! 411: return tmp & 0xffff;
! 412: }
! 413:
! 414: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
! 415: // count は 0..63
! 416: uint32
! 417: m68030acc::asl_32(uint32 data, int count)
! 418: {
! 419: if (count == 0) {
! 420: move_32(data);
! 421: return data;
! 422: }
! 423: int64 tmps = (int64)(int32)data;
! 424: if (count > 32) count = 33;
! 425: uint64 tmp = (uint64)tmps << count;
! 426: X = C = tmp >> 32;
! 427: N = Z = tmp;
! 428: // 送り出された全てのビットが元の MSB と一致すれば V=0
! 429: SetV(((int64)tmp >> 31) != (tmps >> 32));
! 430: return tmp;
! 431: }
! 432:
! 433: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
! 434: // count は 0..63。data の上位はクリアしておくこと。
! 435: uint32
! 436: m68030acc::lsl_8(uint32 data, int count)
! 437: {
! 438: if (count == 0) {
! 439: move_8(data);
! 440: return data;
! 441: }
! 442: uint64 tmp = (uint64)data << count;
! 443: X = C = tmp >> 8;
! 444: N = tmp << 24;
! 445: Z = tmp & 0xff;
! 446: V = 0;
! 447: return Z;
! 448: }
! 449:
! 450: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
! 451: // count は 0..63。data の上位はクリアしておくこと。
! 452: uint32
! 453: m68030acc::lsl_16(uint32 data, int count)
! 454: {
! 455: if (count == 0) {
! 456: move_16(data);
! 457: return data;
! 458: }
! 459: uint64 tmp = (uint64)data << count;
! 460: X = C = tmp >> 16;
! 461: N = tmp << 16;
! 462: Z = tmp & 0xffff;
! 463: V = 0;
! 464: return Z;
! 465: }
! 466:
! 467: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
! 468: // count は 0..63
! 469: uint32
! 470: m68030acc::lsl_32(uint32 data, int count)
! 471: {
! 472: if (count == 0) {
! 473: move_32(data);
! 474: return data;
! 475: }
! 476: uint64 tmp = (uint64)data << count;
! 477: X = C = tmp >> 32;
! 478: N = tmp;
! 479: Z = tmp;
! 480: V = 0;
! 481: return Z;
! 482: }
! 483:
! 484: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
! 485: // count は 0..63
! 486: uint32
! 487: m68030acc::roxl_8(uint32 data, int count)
! 488: {
! 489: count %= 9;
! 490: if (count == 0) {
! 491: Z = data;
! 492: N = data << 24;
! 493: V = 0;
! 494: C = X;
! 495: return Z;
! 496: }
! 497: uint32 xbit = X & 1;
! 498: Z = (data << count) | (data >> (9 - count)) | (xbit << (count - 1));
! 499: C = X = Z >> 8;
! 500: Z &= 0xff;
! 501: N = Z << 24;
! 502: V = 0;
! 503: return Z;
! 504: }
! 505:
! 506: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
! 507: // count は 0..63
! 508: uint32
! 509: m68030acc::roxl_16(uint32 data, int count)
! 510: {
! 511: count %= 17;
! 512: if (count == 0) {
! 513: Z = data;
! 514: N = data << 16;
! 515: V = 0;
! 516: C = X;
! 517: return Z;
! 518: }
! 519: uint32 xbit = X & 1;
! 520: Z = (data << count) | (data >> (17 - count)) | (xbit << (count - 1));
! 521: C = X = Z >> 16;
! 522: Z &= 0xffff;
! 523: N = Z << 16;
! 524: V = 0;
! 525: return Z;
! 526: }
! 527:
! 528: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
! 529: // count は 0..63
! 530: uint32
! 531: m68030acc::roxl_32(uint32 data, int count)
! 532: {
! 533: count %= 33;
! 534: if (count == 0) {
! 535: Z = data;
! 536: N = data;
! 537: V = 0;
! 538: C = X;
! 539: return Z;
! 540: }
! 541: // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
! 542: uint64 data64 = data;
! 543: uint32 xbit = X & 1;
! 544: Z = (data64 << count) | (data64 >> (33 - count)) | (xbit << (count - 1));
! 545: C = X = data64 >> (32 - count);
! 546: N = Z;
! 547: V = 0;
! 548: return Z;
! 549: }
! 550:
! 551: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
! 552: // count は 0..63。data の上位はクリアしておくこと
! 553: uint32
! 554: m68030acc::rol_8(uint32 data, int count)
! 555: {
! 556: if (count == 0) {
! 557: move_8(data);
! 558: return data;
1.1 root 559: }
560:
1.1.1.3 ! root 561: count %= 8;
! 562: int count2 = (8 - count) % 8;
! 563: uint8 tmp = (data << count) | (data >> count2);
! 564: Z = tmp;
! 565: N = (uint32)tmp << 24;
! 566: C = data >> count2;
! 567: V = 0;
! 568: return Z;
1.1 root 569: }
570:
1.1.1.3 ! root 571: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
! 572: // count は 0..63。data の上位はクリアしておくこと
! 573: uint32
! 574: m68030acc::rol_16(uint32 data, int count)
1.1 root 575: {
1.1.1.3 ! root 576: if (count == 0) {
! 577: move_16(data);
! 578: return data;
! 579: }
1.1 root 580:
1.1.1.3 ! root 581: count %= 16;
! 582: int count2 = (16 - count) % 16;
! 583: uint16 tmp = (data << count) | (data >> count2);
! 584: Z = tmp;
! 585: N = (uint32)tmp << 16;
! 586: C = data >> count2;
! 587: V = 0;
! 588: return Z;
1.1 root 589: }
590:
1.1.1.3 ! root 591: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
! 592: // count は 0..63
! 593: uint32
! 594: m68030acc::rol_32(uint32 data, int count)
! 595: {
! 596: if (count == 0) {
! 597: move_32(data);
! 598: return data;
! 599: }
! 600:
! 601: count %= 32;
! 602: int count2 = (32 - count) % 32;
! 603: uint64 data64 = (uint64)data;
! 604: uint64 tmp = (data << count) | (data >> count2);
! 605: Z = tmp;
! 606: N = Z;
! 607: C = data64 >> count2;
! 608: V = 0;
! 609: return Z;
! 610: }
! 611:
! 612: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
! 613: // count は 0..64。data の上位はクリアしておくこと。
! 614: uint32
! 615: m68030acc::asr_8(uint32 data, int count)
1.1 root 616: {
1.1.1.3 ! root 617: if (count == 0) {
! 618: move_8(data);
! 619: return data;
! 620: }
! 621: if (count > 8) {
! 622: if ((int8)data < 0) {
! 623: data = 0xff;
1.1 root 624: } else {
1.1.1.3 ! root 625: data = 0;
1.1 root 626: }
1.1.1.3 ! root 627: X = C = Z = data;
! 628: N = data << 24;
! 629: V = 0;
! 630: return data;
! 631: }
! 632: // data >>> count の結果が tmp の上位32ビット中の下位8ビットに入る
! 633: uint64 tmp = (uint64)(int64)(int8)data << (32 - count);
! 634: X = C = tmp >> 31;
! 635: N = tmp >> 8;
! 636: Z = (tmp >> 32) & 0xff;
! 637: V = 0;
! 638: return Z;
! 639: }
! 640:
! 641: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
! 642: // count は 0..64。data の上位はクリアしておくこと。
! 643: uint32
! 644: m68030acc::asr_16(uint32 data, int count)
! 645: {
! 646: if (count == 0) {
! 647: move_16(data);
! 648: return data;
! 649: }
! 650: if (count > 16) {
! 651: if ((int16)data < 0) {
! 652: data = 0xffff;
1.1 root 653: } else {
1.1.1.3 ! root 654: data = 0;
1.1 root 655: }
1.1.1.3 ! root 656: X = C = Z = data;
! 657: N = data << 16;
! 658: V = 0;
! 659: return data;
! 660: }
! 661: // data >>> count の結果が tmp の上位32ビット中の下位16ビットに入る
! 662: uint64 tmp = (uint64)(int64)(int16)data << (32 - count);
! 663: X = C = tmp >> 31;
! 664: N = tmp >> 16;
! 665: Z = (tmp >> 32) & 0xffff;
! 666: V = 0;
! 667: return Z;
! 668: }
! 669:
! 670: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
! 671: // count は 0..64
! 672: uint32
! 673: m68030acc::asr_32(uint32 data, int count)
! 674: {
! 675: if (count == 0) {
! 676: move_32(data);
! 677: return data;
! 678: }
! 679: if (count > 32) {
! 680: if ((int32)data < 0) {
! 681: data = 0xffffffff;
! 682: } else {
! 683: data = 0;
! 684: }
! 685: X = C = Z = data;
! 686: N = data;
! 687: V = 0;
! 688: return data;
! 689: }
! 690: // data >>> count の結果が tmp の上位32ビットに入る
! 691: uint64 tmp = (uint64)(int64)(int32)data << (32 - count);
! 692: X = C = tmp >> 31;
! 693: Z = N = tmp >> 32;
! 694: V = 0;
! 695: return Z;
! 696: }
! 697:
! 698: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
! 699: // count は 0..63
! 700: uint32
! 701: m68030acc::lsr_8(uint32 data, int count)
! 702: {
! 703: if (count == 0) {
! 704: move_8(data);
! 705: return data;
! 706: }
! 707: if (count > 8) {
! 708: X = C = 0;
! 709: move_8(0);
! 710: return 0;
! 711: }
! 712: // data >> count の結果が tmp の上位32ビットに入る
! 713: uint64 tmp = (uint64)data << (32 - count);
! 714: X = C = tmp >> 31;
! 715: N = tmp >> 8;
! 716: Z = (tmp >> 32) & 0xff;
! 717: V = 0;
! 718: return Z;
! 719: }
! 720:
! 721: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
! 722: // count は 0..63
! 723: uint32
! 724: m68030acc::lsr_16(uint32 data, int count)
! 725: {
! 726: if (count == 0) {
! 727: move_16(data);
! 728: return data;
! 729: }
! 730: if (count > 16) {
! 731: X = C = 0;
! 732: move_16(0);
! 733: return 0;
! 734: }
! 735: // data >> count の結果が tmp の上位32ビットに入る
! 736: uint64 tmp = (uint64)data << (32 - count);
! 737: X = C = tmp >> 31;
! 738: N = tmp >> 16;
! 739: Z = (tmp >> 32) & 0xffff;
! 740: V = 0;
! 741: return Z;
! 742: }
! 743:
! 744: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
! 745: // count は 0..63
! 746: uint32
! 747: m68030acc::lsr_32(uint32 data, int count)
! 748: {
! 749: if (count == 0) {
! 750: move_32(data);
! 751: return data;
! 752: }
! 753: if (count > 32) {
! 754: X = C = 0;
! 755: move_32(0);
! 756: return 0;
! 757: }
! 758: // data >> count の結果が tmp の上位32ビットに入る
! 759: uint64 tmp = (uint64)data << (32 - count);
! 760: X = C = tmp >> 31;
! 761: Z = N = tmp >> 32;
! 762: V = 0;
! 763: return Z;
! 764: }
! 765:
! 766: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
! 767: // count は 0..63
! 768: uint32
! 769: m68030acc::roxr_8(uint32 data, int count)
! 770: {
! 771: count %= 9;
! 772: if (count == 0) {
! 773: Z = data;
! 774: N = data << 24;
! 775: V = 0;
! 776: C = X;
! 777: return Z;
! 778: }
! 779: uint32 rot = data & ((1 << (count - 1)) - 1);
! 780: uint32 xbit = X & 1;
! 781: Z = (data >> count) | (rot << (9 - count)) | (xbit << (8 - count));
! 782: C = X = data >> (count - 1);
! 783: N = Z << 24;
! 784: V = 0;
! 785: return Z;
! 786: }
! 787:
! 788: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
! 789: // count は 0..63
! 790: uint32
! 791: m68030acc::roxr_16(uint32 data, int count)
! 792: {
! 793: count %= 17;
! 794: if (count == 0) {
! 795: Z = data;
! 796: N = data << 16;
! 797: V = 0;
! 798: C = X;
! 799: return Z;
! 800: }
! 801: uint32 rot = data & ((1 << (count - 1)) - 1);
! 802: uint32 xbit = X & 1;
! 803: Z = (data >> count) | (rot << (17 - count)) | (xbit << (16 - count));
! 804: C = X = data >> (count - 1);
! 805: N = Z << 16;
! 806: V = 0;
! 807: return Z;
! 808: }
! 809:
! 810: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
! 811: // count は 0..63
! 812: uint32
! 813: m68030acc::roxr_32(uint32 data, int count)
! 814: {
! 815: count %= 33;
! 816: if (count == 0) {
! 817: Z = data;
! 818: N = data;
! 819: V = 0;
! 820: C = X;
! 821: return Z;
! 822: }
! 823: // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
! 824: uint64 data64 = data;
! 825: uint64 rot = data64 & ((1 << (count - 1)) - 1);
! 826: uint32 xbit = X & 1;
! 827: Z = (data64 >> count) | (rot << (33 - count)) | (xbit << (32 - count));
! 828: C = X = data64 >> (count - 1);
! 829: N = Z;
! 830: V = 0;
! 831: return Z;
! 832: }
! 833:
! 834: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
! 835: // count は 0..63
! 836: uint32
! 837: m68030acc::ror_8(uint32 data, int count)
! 838: {
! 839: if (count == 0) {
! 840: move_8(data);
! 841: return data;
1.1 root 842: }
1.1.1.3 ! root 843:
! 844: count %= 8;
! 845: uint8 tmp = (data >> count) | (data << (8 - count));
! 846: Z = tmp;
! 847: N = (uint32)tmp << 24;
! 848: // 7 0 1 2 3 4 5 6
! 849: C = data >> ((count + 7) % 8);
! 850: V = 0;
! 851: return tmp;
! 852: }
! 853:
! 854: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
! 855: // count は 0..63
! 856: uint32
! 857: m68030acc::ror_16(uint32 data, int count)
! 858: {
! 859: if (count == 0) {
! 860: move_16(data);
! 861: return data;
! 862: }
! 863:
! 864: count %= 16;
! 865: uint16 tmp = (data >> count) | (data << (16 - count));
! 866: Z = tmp;
! 867: N = (uint32)tmp << 16;
! 868: C = data >> ((count + 15) % 16);
! 869: V = 0;
! 870: return tmp;
! 871: }
! 872:
! 873: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
! 874: // count は 0..63
! 875: uint32
! 876: m68030acc::ror_32(uint32 data, int count)
! 877: {
! 878: if (count == 0) {
! 879: move_32(data);
! 880: return data;
! 881: }
! 882:
! 883: count %= 32;
! 884: uint64 data64 = (uint64)data;
! 885: uint64 tmp = (data >> count) | (data << (32 - count));
! 886: Z = tmp;
! 887: N = tmp;
! 888: C = data64 >> ((count + 31) % 32);
! 889: V = 0;
! 890: return tmp;
1.1 root 891: }
892:
893: void
1.1.1.3 ! root 894: m68030acc::chk2cmp2_32(uint32 compare, uint32 lower, uint32 upper)
1.1 root 895: {
896: // 実機の実行結果をじっと睨んだ結果、このロジックで
897: // cmp2 は実行していると考えられる。
898: // オペランド順はフラグに影響する。
899: // なぜ 68k のデザイナが順序を入れ替えたのかは不明。
900: // なんかの都合があったんだろうな...
901:
902: // この cmp は通常の if で代替できるけど、
903: // あえて MPU 内部の動作をエミュレート。
1.1.1.3 ! root 904: cmp_32(lower, upper);
1.1 root 905:
1.1.1.3 ! root 906: if (CondCS()) {
! 907: cmp_32(compare, upper);
! 908: if (CondEQ()) {
1.1 root 909: // break
1.1.1.3 ! root 910: } else if (CondCS()) {
! 911: cmp_32(lower, compare);
1.1 root 912: } else {
1.1.1.3 ! root 913: cmp_32(compare, lower);
1.1 root 914: }
915: } else {
1.1.1.3 ! root 916: cmp_32(lower, compare);
! 917: if (CondEQ()) {
1.1 root 918: // break
1.1.1.3 ! root 919: } else if (CondCS()) {
1.1 root 920: // break
921: } else {
1.1.1.3 ! root 922: cmp_32(compare, upper);
1.1 root 923: }
924: }
925: }
926:
927: // src_10 + dst_10 + X を計算し、XNZVC フラグをセットして結果を返す。
928: // src, dst の上位ビットはクリアしておくこと。
929: // 戻り値の上位ビットはクリアされている。
930: uint32
1.1.1.3 ! root 931: m68030acc::abcd_8(uint32 src, uint32 dst)
1.1 root 932: {
933: uint32 res;
934: uint32 tmp;
935: uint32 adj;
936: uint32 low;
1.1.1.3 ! root 937: uint32 cbit;
1.1 root 938:
939: adj = 0;
1.1.1.3 ! root 940: cbit = 0;
1.1 root 941:
942: // X フラグは LSB なので直接足してよい
1.1.1.3 ! root 943: tmp = src + dst + (X & X_BIT);
1.1 root 944:
1.1.1.3 ! root 945: low = (src & 0x0f) + (dst & 0x0f) + (X & X_BIT);
1.1 root 946: if (low > 0x09) {
947: adj = 0x06;
948: }
949:
950: if (tmp > 0x99) {
951: adj += 0x60;
1.1.1.3 ! root 952: cbit = C_BIT;
1.1 root 953: }
954:
955: res = tmp + adj;
1.1.1.3 ! root 956: cbit |= res >> 8;
! 957: X = C = cbit;
1.1 root 958:
959: res &= 0xff;
1.1.1.3 ! root 960: Z |= res;
1.1 root 961:
962: // V フラグは不定だが 68030 では常にクリア
1.1.1.3 ! root 963: V = 0;
1.1 root 964: // N フラグは不定だが 68030 実機合わせ
1.1.1.3 ! root 965: N = res << 24;
1.1 root 966:
967: return res;
968: }
969:
970: // src_10 - dst_10 - X を計算し、XNZVC フラグをセットして結果を返す。
971: // src, dst の上位ビットはクリアしておくこと。
972: // 戻り値の上位ビットはクリアされている。
973: uint32
1.1.1.3 ! root 974: m68030acc::sbcd_8(uint32 src, uint32 dst)
1.1 root 975: {
976: uint32 res;
977: int32 tmp;
978: int32 adj;
979: int32 low;
1.1.1.3 ! root 980: uint32 cbit;
1.1 root 981:
982: adj = 0;
1.1.1.3 ! root 983: cbit = 0;
1.1 root 984:
985: // X フラグは LSB なので直接引いてよい
1.1.1.3 ! root 986: tmp = dst - src - (X & X_BIT);
1.1 root 987:
1.1.1.3 ! root 988: low = (dst & 0x0f) - (src & 0x0f) - (X & X_BIT);
1.1 root 989: if (low < 0) {
990: adj = 0x06;
991: }
992:
993: if (tmp < 0) {
994: adj += 0x60;
1.1.1.3 ! root 995: cbit = C_BIT;
1.1 root 996: }
997:
998: res = tmp - adj;
1.1.1.3 ! root 999: cbit |= res >> 8;
! 1000: X = C = cbit;
1.1 root 1001:
1002: res &= 0xff;
1.1.1.3 ! root 1003: Z |= res;
1.1 root 1004:
1005: // V フラグは不定だが 68030 では常にクリア
1.1.1.3 ! root 1006: V = 0;
1.1 root 1007: // N フラグは不定だが 68030 実機合わせ
1.1.1.3 ! root 1008: N = res << 24;
1.1 root 1009:
1010: return res;
1011: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.