|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: #include "mpu680x0.h" ! 8: #include "m680x0acc.h" ! 9: ! 10: /*static*/ inline uint32 ! 11: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: } ! 167: ! 168: // dst - src を計算し、NZVC フラグをセットして結果を返す。 ! 169: uint32 ! 170: m680x0ACC::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: } ! 177: ! 178: // dst - src を計算し、XNZVC フラグをセットして結果を返す。 ! 179: // src, dst の上位ビットはクリアしておくこと。 ! 180: // 戻り値の上位ビットはクリアされている。 ! 181: uint32 ! 182: m680x0ACC::sub_8(uint32 src, uint32 dst) ! 183: { ! 184: uint32 res = cmp_8(src, dst); ! 185: X = C; ! 186: return res; ! 187: } ! 188: ! 189: // dst - src を計算し、XNZVC フラグをセットして結果を返す。 ! 190: // src, dst の上位ビットはクリアしておくこと。 ! 191: // 戻り値の上位ビットはクリアされている。 ! 192: uint32 ! 193: m680x0ACC::sub_16(uint32 src, uint32 dst) ! 194: { ! 195: uint32 res = cmp_16(src, dst); ! 196: X = C; ! 197: return res; ! 198: } ! 199: ! 200: // dst - src を計算し、XNZVC フラグをセットして結果を返す。 ! 201: uint32 ! 202: m680x0ACC::sub_32(uint32 src, uint32 dst) ! 203: { ! 204: uint32 res = cmp_32(src, dst); ! 205: X = C; ! 206: return res; ! 207: } ! 208: ! 209: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。 ! 210: // src, dst の上位ビットはクリアしておくこと。 ! 211: // 戻り値 res の上位ビットはクリアされている。 ! 212: uint32 ! 213: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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; ! 293: } else { ! 294: V = 0; ! 295: } ! 296: return (uint32)res; ! 297: } ! 298: ! 299: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(32bit)を返す。 ! 300: uint32 ! 301: m680x0ACC::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; ! 315: } ! 316: return (uint32)res; ! 317: } ! 318: ! 319: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(64bit)を返す。 ! 320: uint64 ! 321: m680x0ACC::mulu_64(uint32 src, uint32 dst) ! 322: { ! 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: m680x0ACC::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; ! 341: } ! 342: ! 343: void ! 344: m680x0ACC::btst(uint32 data, int n) ! 345: { ! 346: Z = data & (1 << n); ! 347: } ! 348: ! 349: uint32 ! 350: m680x0ACC::bchg(uint32 data, int n) ! 351: { ! 352: Z = data & (1 << n); ! 353: data ^= (1 << n); ! 354: return data; ! 355: } ! 356: ! 357: uint32 ! 358: m680x0ACC::bclr(uint32 data, int n) ! 359: { ! 360: Z = data & (1 << n); ! 361: data &= ~(1 << n); ! 362: return data; ! 363: } ! 364: ! 365: uint32 ! 366: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::rol_8(uint32 data, int count) ! 555: { ! 556: if (count == 0) { ! 557: move_8(data); ! 558: return data; ! 559: } ! 560: ! 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; ! 569: } ! 570: ! 571: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。 ! 572: // count は 0..63。data の上位はクリアしておくこと ! 573: uint32 ! 574: m680x0ACC::rol_16(uint32 data, int count) ! 575: { ! 576: if (count == 0) { ! 577: move_16(data); ! 578: return data; ! 579: } ! 580: ! 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; ! 589: } ! 590: ! 591: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。 ! 592: // count は 0..63 ! 593: uint32 ! 594: m680x0ACC::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: m680x0ACC::asr_8(uint32 data, int count) ! 616: { ! 617: if (count == 0) { ! 618: move_8(data); ! 619: return data; ! 620: } ! 621: if (count > 8) { ! 622: if ((int8)data < 0) { ! 623: data = 0xff; ! 624: } else { ! 625: data = 0; ! 626: } ! 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: m680x0ACC::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; ! 653: } else { ! 654: data = 0; ! 655: } ! 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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::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: m680x0ACC::ror_8(uint32 data, int count) ! 838: { ! 839: if (count == 0) { ! 840: move_8(data); ! 841: return data; ! 842: } ! 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: m680x0ACC::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: m680x0ACC::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; ! 891: } ! 892: ! 893: void ! 894: m680x0ACC::chk2cmp2_32(uint32 compare, uint32 lower, uint32 upper) ! 895: { ! 896: // 実機の実行結果をじっと睨んだ結果、このロジックで ! 897: // cmp2 は実行していると考えられる。 ! 898: // オペランド順はフラグに影響する。 ! 899: // なぜ 68k のデザイナが順序を入れ替えたのかは不明。 ! 900: // なんかの都合があったんだろうな... ! 901: ! 902: // この cmp は通常の if で代替できるけど、 ! 903: // あえて MPU 内部の動作をエミュレート。 ! 904: cmp_32(lower, upper); ! 905: ! 906: if (CondCS()) { ! 907: cmp_32(compare, upper); ! 908: if (CondEQ()) { ! 909: // break ! 910: } else if (CondCS()) { ! 911: cmp_32(lower, compare); ! 912: } else { ! 913: cmp_32(compare, lower); ! 914: } ! 915: } else { ! 916: cmp_32(lower, compare); ! 917: if (CondEQ()) { ! 918: // break ! 919: } else if (CondCS()) { ! 920: // break ! 921: } else { ! 922: cmp_32(compare, upper); ! 923: } ! 924: } ! 925: } ! 926: ! 927: // src_10 + dst_10 + X を計算し、XNZVC フラグをセットして結果を返す。 ! 928: // src, dst の上位ビットはクリアしておくこと。 ! 929: // 戻り値の上位ビットはクリアされている。 ! 930: uint32 ! 931: m680x0ACC::abcd_8(uint32 src, uint32 dst) ! 932: { ! 933: uint32 res; ! 934: uint32 tmp; ! 935: uint32 adj; ! 936: uint32 low; ! 937: uint32 cbit; ! 938: ! 939: adj = 0; ! 940: cbit = 0; ! 941: ! 942: // X フラグは LSB なので直接足してよい ! 943: tmp = src + dst + (X & X_BIT); ! 944: ! 945: low = (src & 0x0f) + (dst & 0x0f) + (X & X_BIT); ! 946: if (low > 0x09) { ! 947: adj = 0x06; ! 948: } ! 949: ! 950: if (tmp > 0x99) { ! 951: adj += 0x60; ! 952: cbit = C_BIT; ! 953: } ! 954: ! 955: res = tmp + adj; ! 956: cbit |= res >> 8; ! 957: X = C = cbit; ! 958: ! 959: res &= 0xff; ! 960: Z |= res; ! 961: ! 962: // V フラグは不定だが 68030 では常にクリア ! 963: V = 0; ! 964: // N フラグは不定だが 68030 実機合わせ ! 965: N = res << 24; ! 966: ! 967: return res; ! 968: } ! 969: ! 970: // src_10 - dst_10 - X を計算し、XNZVC フラグをセットして結果を返す。 ! 971: // src, dst の上位ビットはクリアしておくこと。 ! 972: // 戻り値の上位ビットはクリアされている。 ! 973: uint32 ! 974: m680x0ACC::sbcd_8(uint32 src, uint32 dst) ! 975: { ! 976: uint32 res; ! 977: int32 tmp; ! 978: int32 adj; ! 979: int32 low; ! 980: uint32 cbit; ! 981: ! 982: adj = 0; ! 983: cbit = 0; ! 984: ! 985: // X フラグは LSB なので直接引いてよい ! 986: tmp = dst - src - (X & X_BIT); ! 987: ! 988: low = (dst & 0x0f) - (src & 0x0f) - (X & X_BIT); ! 989: if (low < 0) { ! 990: adj = 0x06; ! 991: } ! 992: ! 993: if (tmp < 0) { ! 994: adj += 0x60; ! 995: cbit = C_BIT; ! 996: } ! 997: ! 998: res = tmp - adj; ! 999: cbit |= res >> 8; ! 1000: X = C = cbit; ! 1001: ! 1002: res &= 0xff; ! 1003: Z |= res; ! 1004: ! 1005: // V フラグは不定だが 68030 では常にクリア ! 1006: V = 0; ! 1007: // N フラグは不定だが 68030 実機合わせ ! 1008: N = res << 24; ! 1009: ! 1010: return res; ! 1011: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.