--- nono/m680x0/m68030acc.h 2026/04/29 17:04:28 1.1 +++ nono/m680x0/m68030acc.h 2026/04/29 17:05:15 1.1.1.4 @@ -1,960 +1,99 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #pragma once -extern void acc_chk2cmp2_32(m68kcpu *cpu, uint32, uint32, uint32); -extern bool acc_divu_32_16(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *); -extern bool acc_divu_32_32(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *); -extern bool acc_divu_64_32(m68kcpu *cpu, uint32, uint64, uint32 *, uint32 *); -extern bool acc_divs_32_16(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *); -extern bool acc_divs_32_32(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *); -extern bool acc_divs_64_32(m68kcpu *cpu, uint32, uint64, uint32 *, uint32 *); -extern uint32 acc_abcd_8(m68kcpu *cpu, uint32 src ,uint32 dst); -extern uint32 acc_sbcd_8(m68kcpu *cpu, uint32 src, uint32 dst); - -// ビットフィールド命令 -class acc_bf +class m68030acc : public m68030ccr { public: - acc_bf(m68kcpu *); - // デストラクタは無し。 - - void LoadReg(uint n); // Dn から値を読み込む - void LoadMem(uint32 addr); // メモリから値を読み込む - - // レジスタまたはメモリにストアする - void Store(uint n) { - if (n < 8) { - StoreReg(n); - } else { - StoreMem(); - } - }; - - uint32 data = 0; // 32bit 左詰めデータ - int32 offset = 0; // (第2ワードで指定された) オフセット - uint32 width = 0; // 幅 + // res を元に NZVC フラグをセットする。 + // res の上位ビットは無視される。 + inline void move_8(uint32 res) { + Z = res << 24; + N = Z; + C = 0; + V = 0; + } + + // res を元に NZVC フラグをセットする。 + // res の上位ビットは無視される。 + inline void move_16(uint32 res) { + Z = res << 16; + N = Z; + C = 0; + V = 0; + } + + // res を元に NZVC フラグをセットする。 + inline void move_32(uint32 res) { + Z = res; + N = res; + C = 0; + V = 0; + } + + uint32 add_8(uint32, uint32); + uint32 add_16(uint32, uint32); + uint32 add_32(uint32, uint32); + uint32 addx_8(uint32, uint32); + uint32 addx_16(uint32, uint32); + uint32 addx_32(uint32, uint32); + uint32 cmp_8(uint32, uint32); + uint32 cmp_16(uint32, uint32); + uint32 cmp_32(uint32, uint32); + uint32 sub_8(uint32, uint32); + uint32 sub_16(uint32, uint32); + uint32 sub_32(uint32, uint32); + uint32 subx_8(uint32, uint32); + uint32 subx_16(uint32, uint32); + uint32 subx_32(uint32, uint32); + uint32 mulu_16(uint32, uint32); + uint32 muls_16(uint32, uint32); + uint32 mulu_32(uint32, uint32); + uint32 muls_32(uint32, uint32); + uint64 mulu_64(uint32, uint32); + uint64 muls_64(uint32, uint32); + void btst(uint32, int); + uint32 bchg(uint32, int); + uint32 bclr(uint32, int); + uint32 bset(uint32, int); + uint32 asl_8(uint32, int); + uint32 asl_16(uint32, int); + uint32 asl_32(uint32, int); + uint32 lsl_8(uint32, int); + uint32 lsl_16(uint32, int); + uint32 lsl_32(uint32, int); + uint32 roxl_8(uint32, int); + uint32 roxl_16(uint32, int); + uint32 roxl_32(uint32, int); + uint32 rol_8(uint32, int); + uint32 rol_16(uint32, int); + uint32 rol_32(uint32, int); + uint32 asr_8(uint32, int); + uint32 asr_16(uint32, int); + uint32 asr_32(uint32, int); + uint32 lsr_8(uint32, int); + uint32 lsr_16(uint32, int); + uint32 lsr_32(uint32, int); + uint32 roxr_8(uint32, int); + uint32 roxr_16(uint32, int); + uint32 roxr_32(uint32, int); + uint32 ror_8(uint32, int); + uint32 ror_16(uint32, int); + uint32 ror_32(uint32, int); + + void chk2cmp2_32(uint32, uint32, uint32); + uint32 abcd_8(uint32 src ,uint32 dst); + uint32 sbcd_8(uint32 src, uint32 dst); private: - void StoreReg(uint n); // 値を Dn に書き出す - void StoreMem(); // 値をメモリに書き出す - - // 32ビットの val を count ビット左ローテートした値を返す。 - // count は 0..31。 - // 実際には count==0 の時 (val>>32) となりこれは未定義動作なのだが - // ぶっちゃけこの形式はローテート命令一発に変換されると知っているので - // とりあえず放置しておく。C++20 になったら std::rotl() を検討。 - NO_SANITIZE("undefined") - uint32 ROL32(uint32 val, uint count) { - return (val << count) | (val >> (32 - count)); - } - - // 32ビットの val を count ビット右ローテートした値を返す。 - // count は 0..31。 - // 実際には count==0 の時 (val>>32) となりこれは未定義動作なのだが - // ぶっちゃけこの形式はローテート命令一発に変換されると知っているので - // とりあえず放置しておく。C++20 になったら std::rotr() を検討。 - NO_SANITIZE("undefined") - uint32 ROR32(uint32 val, uint count) { - return (val >> count) | (val << (32 - count)); - } - - m68kcpu *cpu = NULL; - - uint32 mask = 0; // 32ビット左詰めマスク - uint32 ea = 0; // オフセット計算後の EA - int32 local_offset = 0; // 内部(32bit or 8bit 内)オフセット - int bytes = 0; // アクセスバイト数 - uint64 buf = 0; // 40ビットのメモリバッファ + static inline uint32 vflag_add_8(uint32 src, uint32 dst, uint32 res); + static inline uint32 vflag_add_16(uint32 src, uint32 dst, uint32 res); + static inline uint32 vflag_add_32(uint32 src, uint32 dst, uint32 res); + static inline uint32 vflag_sub_8(uint32 src, uint32 dst, uint32 res); + static inline uint32 vflag_sub_16(uint32 src, uint32 dst, uint32 res); + static inline uint32 vflag_sub_32(uint32 src, uint32 dst, uint32 res); }; - -// res を元に NZVC フラグをセットする。 -// res の上位ビットは無視される。 -static inline void -acc_move_8(m68kcpu *cpu, uint32 res) -{ - CCR.z = res << 24; - CCR.n = CCR.z; - CCR.c = 0; - CCR.v = 0; -} - -// res を元に NZVC フラグをセットする。 -// res の上位ビットは無視される。 -static inline void -acc_move_16(m68kcpu *cpu, uint32 res) -{ - CCR.z = res << 16; - CCR.n = CCR.z; - CCR.c = 0; - CCR.v = 0; -} - -// res を元に NZVC フラグをセットする。 -static inline void -acc_move_32(m68kcpu *cpu, uint32 res) -{ - CCR.z = res; - CCR.n = res; - CCR.c = 0; - CCR.v = 0; -} - - -#define vflag_add_8(src, dst, res) (vflag_add_32(src, dst, res) << 24) -#define vflag_add_16(src, dst, res) (vflag_add_32(src, dst, res) << 16) -#define vflag_add_32(src, dst, res) (((src) ^ (res)) & ((dst) ^ (res))) - -// src + dst を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_add_8(m68kcpu *cpu, uint32 src, uint32 dst) -{ - CCR.z = dst + src; - CCR.c = CCR.z >> 8; - CCR.x = CCR.c; - CCR.n = CCR.z << 24; - CCR.z &= 0xff; - CCR.v = vflag_add_8(src, dst, CCR.z); - return CCR.z; -} - -// src + dst を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_add_16(m68kcpu *cpu, uint32 src, uint32 dst) -{ - CCR.z = dst + src; - CCR.c = CCR.z >> 16; - CCR.x = CCR.c; - CCR.n = CCR.z << 16; - CCR.z &= 0xffff; - CCR.v = vflag_add_16(src, dst, CCR.z); - return CCR.z; -} - -// src + dst を計算し、XNZVC フラグをセットして結果を返す。 -static inline uint32 -acc_add_32(m68kcpu *cpu, uint32 src, uint32 dst) -{ - CCR.cz = (uint64)dst + (uint64)src; - CCR.x = CCR.c; - CCR.v = vflag_add_32(src, dst, CCR.z); - CCR.n = CCR.z; - return CCR.z; -} - -// src + dst + X を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_addx_8(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = dst + src + (CCR.IsX() ? 1 : 0); - CCR.c = res >> 8; - CCR.x = CCR.c; - CCR.n = res << 24; - // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない - if (CCR.n != 0) { - CCR.z = CCR.n; - } - CCR.v = vflag_add_8(src, dst, res); - return res & 0xff; -} - -// src + dst + X を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_addx_16(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = dst + src + (CCR.IsX() ? 1 : 0); - CCR.c = res >> 16; - CCR.x = CCR.c; - CCR.n = res << 16; - // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない - if (CCR.n != 0) { - CCR.z = CCR.n; - } - CCR.v = vflag_add_16(src, dst, res); - return res & 0xffff; -} - -// src + dst + X を計算し、XNZVC フラグをセットして結果を返す。 -static inline uint32 -acc_addx_32(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint64 res = (uint64)dst + (uint64)src + (CCR.IsX() ? 1 : 0); - CCR.c = res >> 32; - CCR.x = CCR.c; - CCR.n = res; - // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない - if (CCR.n != 0) { - CCR.z = CCR.n; - } - CCR.v = vflag_add_32(src, dst, res); - return res; -} - - -#define vflag_sub_8(src, dst, res) (vflag_sub_32(src, dst, res) << 24) -#define vflag_sub_16(src, dst, res) (vflag_sub_32(src, dst, res) << 16) -#define vflag_sub_32(src, dst, res) (((src) ^ (dst)) & ((dst) ^ (res))) - -// dst - src を計算し、NZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_cmp_8(m68kcpu *cpu, uint32 src, uint32 dst) -{ - CCR.z = dst - src; - CCR.c = CCR.z >> 8; - CCR.n = CCR.z << 24; - CCR.z &= 0xff; - CCR.v = vflag_sub_8(src, dst, CCR.z); - return CCR.z; -} - -// dst - src を計算し、NZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_cmp_16(m68kcpu *cpu, uint32 src, uint32 dst) -{ - CCR.z = dst - src; - CCR.c = CCR.z >> 16; - CCR.n = CCR.z << 16; - CCR.z &= 0xffff; - CCR.v = vflag_sub_16(src, dst, CCR.z); - return CCR.z; -} - -// dst - src を計算し、NZVC フラグをセットして結果を返す。 -static inline uint32 -acc_cmp_32(m68kcpu *cpu, uint32 src, uint32 dst) -{ - CCR.cz = (uint64)dst - (uint64)src; - CCR.n = CCR.z; - CCR.v = vflag_sub_32(src, dst, CCR.z); - return CCR.z; -} - -// dst - src を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_sub_8(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = acc_cmp_8(cpu, src, dst); - CCR.x = CCR.c; - return res; -} - -// dst - src を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値の上位ビットはクリアされている。 -static inline uint32 -acc_sub_16(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = acc_cmp_16(cpu, src, dst); - CCR.x = CCR.c; - return res; -} - -// dst - src を計算し、XNZVC フラグをセットして結果を返す。 -static inline uint32 -acc_sub_32(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = acc_cmp_32(cpu, src, dst); - CCR.x = CCR.c; - return res; -} - -// src - dst - X を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値 res の上位ビットはクリアされている。 -static inline uint32 -acc_subx_8(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = dst - src - (CCR.IsX() ? 1 : 0); - CCR.c = res >> 8; - CCR.x = CCR.c; - CCR.n = res << 24; - // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない - if (CCR.n != 0) { - CCR.z = CCR.n; - } - CCR.v = vflag_sub_8(src, dst, res); - return res & 0xff; -} - -// src - dst - X を計算し、XNZVC フラグをセットして結果を返す。 -// src, dst の上位ビットはクリアしておくこと。 -// 戻り値 res の上位ビットはクリアされている。 -static inline uint32 -acc_subx_16(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = dst - src - (CCR.IsX() ? 1 : 0); - CCR.c = res >> 16; - CCR.x = CCR.c; - CCR.n = res << 16; - // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない - if (CCR.n != 0) { - CCR.z = CCR.n; - } - CCR.v = vflag_sub_16(src, dst, res); - return res & 0xffff; -} - -// src - dst - X を計算し、XNZVC フラグをセットして結果を返す。 -static inline uint32 -acc_subx_32(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint64 res = (uint64)dst - (uint64)src - (CCR.IsX() ? 1 : 0); - CCR.c = res >> 32; - CCR.x = CCR.c; - CCR.n = res; - // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない - if (CCR.n != 0) { - CCR.z = CCR.n; - } - CCR.v = vflag_sub_32(src, dst, res); - return res; -} - -// src(u16) * dst(u16) を計算し、NZVC フラグをセットして結果(u32)を返す。 -// src, dst の上位ビットはクリアしておくこと。 -static inline uint32 -acc_mulu_16(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint32 res = src * dst; - // 16x16->32 ではオーバーフローは起きないので acc_move でよい - acc_move_32(cpu, res); - return res; -} - -// src(s16) * dst(s16) を計算し、NZVC フラグをセットして結果(u32)を返す。 -// src, dst の上位ビットはクリアしておくこと。 -static inline uint32 -acc_muls_16(m68kcpu *cpu, uint32 src, uint32 dst) -{ - int32 res = (int32)(int16)src * (int32)(int16)dst; - // 16x16->32 ではオーバーフローは起きないので acc_move でよい - acc_move_32(cpu, res); - return res; -} - -// src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(32bit)を返す。 -static inline uint32 -acc_mulu_32(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint64 res = (uint64)src * (uint64)dst; - CCR.z = res; - CCR.n = res; - CCR.c = 0; - if (res > 0xffffffffUL) { - CCR.v = m68030ccr::V_BIT; - } else { - CCR.v = 0; - } - return (uint32)res; -} - -// src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(32bit)を返す。 -static inline uint32 -acc_muls_32(m68kcpu *cpu, uint32 src, uint32 dst) -{ - int64 res = (int64)(int32)src * (int64)(int32)dst; - CCR.z = res; - CCR.n = res; - CCR.c = 0; - // V フラグは64ビット演算結果の上位32ビットが - // 下位32ビットの符号拡張になっていなかった場合に立つ。 - // つまり符号付き整数で 32bit 表現と 64bit 表現が一致していなければ立つ。 - int32 tmp = res; - if (res != tmp) { - CCR.v = m68030ccr::V_BIT; - } else { - CCR.v = 0; - } - return (uint32)res; -} - -// src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(64bit)を返す。 -static inline uint64 -acc_mulu_64(m68kcpu *cpu, uint32 src, uint32 dst) -{ - uint64 res = (uint64)src * (uint64)dst; - CCR.n = res >> 32; - CCR.z = CCR.n | res; - CCR.v = 0; - CCR.c = 0; - return res; -} - -// src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(64bit)を返す。 -static inline uint64 -acc_muls_64(m68kcpu *cpu, uint32 src, uint32 dst) -{ - int64 res = (int64)(int32)src * (int64)(int32)dst; - CCR.n = res >> 32; - CCR.z = CCR.n | res; - CCR.v = 0; - CCR.c = 0; - return res; -} - -static inline void -acc_btst(m68kcpu *cpu, uint32 data, int n) -{ - CCR.z = data & (1 << n); -} - -static inline uint32 -acc_bchg(m68kcpu *cpu, uint32 data, int n) -{ - CCR.z = data & (1 << n); - data ^= (1 << n); - return data; -} - -static inline uint32 -acc_bclr(m68kcpu *cpu, uint32 data, int n) -{ - CCR.z = data & (1 << n); - data &= ~(1 << n); - return data; -} - -static inline uint32 -acc_bset(m68kcpu *cpu, uint32 data, int n) -{ - CCR.z = data & (1 << n); - data |= (1 << n); - return data; -} - - -// data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..63。data の上位はクリアしておくこと。 -static inline uint32 -acc_asl_8(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_8(cpu, data); - return data; - } - int64 tmps = (int64)(int8)data; - if (count > 8) count = 9; - uint64 tmp = (uint64)tmps << count; - CCR.x = CCR.c = tmp >> 8; - CCR.n = tmp << 24; - CCR.z = CCR.n; - // 送り出された全てのビットが元の MSB と一致すれば V=0 - CCR.PutV(((int64)tmp >> 7) != (tmps >> 8)); - return tmp & 0xff; -} - -// data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..63。data の上位はクリアしておくこと。 -static inline uint32 -acc_asl_16(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_16(cpu, data); - return data; - } - int64 tmps = (int64)(int16)data; - if (count > 16) count = 17; - uint64 tmp = (uint64)tmps << count; - CCR.x = CCR.c = tmp >> 16; - CCR.n = tmp << 16; - CCR.z = CCR.n; - // 送り出された全てのビットが元の MSB と一致すれば V=0 - CCR.PutV(((int64)tmp >> 15) != (tmps >> 16)); - return tmp & 0xffff; -} - -// data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_asl_32(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_32(cpu, data); - return data; - } - int64 tmps = (int64)(int32)data; - if (count > 32) count = 33; - uint64 tmp = (uint64)tmps << count; - CCR.x = CCR.c = tmp >> 32; - CCR.n = CCR.z = tmp; - // 送り出された全てのビットが元の MSB と一致すれば V=0 - CCR.PutV(((int64)tmp >> 31) != (tmps >> 32)); - return tmp; -} - -// data を count ビット左シフトし、NZVC フラグを反映して結果を返す。 -// count は 0..63。data の上位はクリアしておくこと。 -static inline uint32 -acc_lsl_8(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_8(cpu, data); - return data; - } - uint64 tmp = (uint64)data << count; - CCR.x = CCR.c = tmp >> 8; - CCR.n = tmp << 24; - CCR.z = tmp & 0xff; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット左シフトし、NZVC フラグを反映して結果を返す。 -// count は 0..63。data の上位はクリアしておくこと。 -static inline uint32 -acc_lsl_16(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_16(cpu, data); - return data; - } - uint64 tmp = (uint64)data << count; - CCR.x = CCR.c = tmp >> 16; - CCR.n = tmp << 16; - CCR.z = tmp & 0xffff; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット左シフトし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_lsl_32(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_32(cpu, data); - return data; - } - uint64 tmp = (uint64)data << count; - CCR.x = CCR.c = tmp >> 32; - CCR.n = tmp; - CCR.z = tmp; - CCR.v = 0; - return CCR.z; -} - -// data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_roxl_8(m68kcpu *cpu, uint32 data, int count) -{ - count %= 9; - if (count == 0) { - CCR.z = data; - CCR.n = data << 24; - CCR.v = 0; - CCR.c = CCR.x; - return CCR.z; - } - uint32 x = CCR.x & 1; - CCR.z = (data << count) | (data >> (9 - count)) | (x << (count - 1)); - CCR.c = CCR.x = CCR.z >> 8; - CCR.z &= 0xff; - CCR.n = CCR.z << 24; - CCR.v = 0; - return CCR.z; -} - -// data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_roxl_16(m68kcpu *cpu, uint32 data, int count) -{ - count %= 17; - if (count == 0) { - CCR.z = data; - CCR.n = data << 16; - CCR.v = 0; - CCR.c = CCR.x; - return CCR.z; - } - uint32 x = CCR.x & 1; - CCR.z = (data << count) | (data >> (17 - count)) | (x << (count - 1)); - CCR.c = CCR.x = CCR.z >> 16; - CCR.z &= 0xffff; - CCR.n = CCR.z << 16; - CCR.v = 0; - return CCR.z; -} - -// data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_roxl_32(m68kcpu *cpu, uint32 data, int count) -{ - count %= 33; - if (count == 0) { - CCR.z = data; - CCR.n = data; - CCR.v = 0; - CCR.c = CCR.x; - return CCR.z; - } - // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用 - uint64 data64 = data; - uint32 x = CCR.x & 1; - CCR.z = (data64 << count) | (data64 >> (33 - count)) | (x << (count - 1)); - CCR.c = CCR.x = data64 >> (32 - count); - CCR.n = CCR.z; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63。data の上位はクリアしておくこと -static inline uint32 -acc_rol_8(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_8(cpu, data); - return data; - } - - count %= 8; - int count2 = (8 - count) % 8; - uint8 tmp = (data << count) | (data >> count2); - CCR.z = tmp; - CCR.n = (uint32)tmp << 24; - CCR.c = data >> count2; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63。data の上位はクリアしておくこと -static inline uint32 -acc_rol_16(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_16(cpu, data); - return data; - } - - count %= 16; - int count2 = (16 - count) % 16; - uint16 tmp = (data << count) | (data >> count2); - CCR.z = tmp; - CCR.n = (uint32)tmp << 16; - CCR.c = data >> count2; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_rol_32(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_32(cpu, data); - return data; - } - - count %= 32; - int count2 = (32 - count) % 32; - uint64 data64 = (uint64)data; - uint64 tmp = (data << count) | (data >> count2); - CCR.z = tmp; - CCR.n = CCR.z; - CCR.c = data64 >> count2; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..64。data の上位はクリアしておくこと。 -static inline uint32 -acc_asr_8(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_8(cpu, data); - return data; - } - if (count > 8) { - if ((int8)data < 0) { - data = 0xff; - } else { - data = 0; - } - CCR.x = CCR.c = CCR.z = data; - CCR.n = data << 24; - CCR.v = 0; - return data; - } - // data >>> count の結果が tmp の上位32ビット中の下位8ビットに入る - uint64 tmp = (uint64)(int64)(int8)data << (32 - count); - CCR.x = CCR.c = tmp >> 31; - CCR.n = tmp >> 8; - CCR.z = (tmp >> 32) & 0xff; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..64。data の上位はクリアしておくこと。 -static inline uint32 -acc_asr_16(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_16(cpu, data); - return data; - } - if (count > 16) { - if ((int16)data < 0) { - data = 0xffff; - } else { - data = 0; - } - CCR.x = CCR.c = CCR.z = data; - CCR.n = data << 16; - CCR.v = 0; - return data; - } - // data >>> count の結果が tmp の上位32ビット中の下位16ビットに入る - uint64 tmp = (uint64)(int64)(int16)data << (32 - count); - CCR.x = CCR.c = tmp >> 31; - CCR.n = tmp >> 16; - CCR.z = (tmp >> 32) & 0xffff; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..64 -static inline uint32 -acc_asr_32(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_32(cpu, data); - return data; - } - if (count > 32) { - if ((int32)data < 0) { - data = 0xffffffff; - } else { - data = 0; - } - CCR.x = CCR.c = CCR.z = data; - CCR.n = data; - CCR.v = 0; - return data; - } - // data >>> count の結果が tmp の上位32ビットに入る - uint64 tmp = (uint64)(int64)(int32)data << (32 - count); - CCR.x = CCR.c = tmp >> 31; - CCR.z = CCR.n = tmp >> 32; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_lsr_8(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_8(cpu, data); - return data; - } - if (count > 8) { - CCR.x = CCR.c = 0; - acc_move_8(cpu, 0); - return 0; - } - // data >> count の結果が tmp の上位32ビットに入る - uint64 tmp = (uint64)data << (32 - count); - CCR.x = CCR.c = tmp >> 31; - CCR.n = tmp >> 8; - CCR.z = (tmp >> 32) & 0xff; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_lsr_16(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_16(cpu, data); - return data; - } - if (count > 16) { - CCR.x = CCR.c = 0; - acc_move_16(cpu, 0); - return 0; - } - // data >> count の結果が tmp の上位32ビットに入る - uint64 tmp = (uint64)data << (32 - count); - CCR.x = CCR.c = tmp >> 31; - CCR.n = tmp >> 16; - CCR.z = (tmp >> 32) & 0xffff; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_lsr_32(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_32(cpu, data); - return data; - } - if (count > 32) { - CCR.x = CCR.c = 0; - acc_move_32(cpu, 0); - return 0; - } - // data >> count の結果が tmp の上位32ビットに入る - uint64 tmp = (uint64)data << (32 - count); - CCR.x = CCR.c = tmp >> 31; - CCR.z = CCR.n = tmp >> 32; - CCR.v = 0; - return CCR.z; -} - -// data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_roxr_8(m68kcpu *cpu, uint32 data, int count) -{ - count %= 9; - if (count == 0) { - CCR.z = data; - CCR.n = data << 24; - CCR.v = 0; - CCR.c = CCR.x; - return CCR.z; - } - uint32 rot = data & ((1 << (count - 1)) - 1); - uint32 x = CCR.x & 1; - CCR.z = (data >> count) | (rot << (9 - count)) | (x << (8 - count)); - CCR.c = CCR.x = data >> (count - 1); - CCR.n = CCR.z << 24; - CCR.v = 0; - return CCR.z; -} - -// data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_roxr_16(m68kcpu *cpu, uint32 data, int count) -{ - count %= 17; - if (count == 0) { - CCR.z = data; - CCR.n = data << 16; - CCR.v = 0; - CCR.c = CCR.x; - return CCR.z; - } - uint32 rot = data & ((1 << (count - 1)) - 1); - uint32 x = CCR.x & 1; - CCR.z = (data >> count) | (rot << (17 - count)) | (x << (16 - count)); - CCR.c = CCR.x = data >> (count - 1); - CCR.n = CCR.z << 16; - CCR.v = 0; - return CCR.z; -} - -// data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_roxr_32(m68kcpu *cpu, uint32 data, int count) -{ - count %= 33; - if (count == 0) { - CCR.z = data; - CCR.n = data; - CCR.v = 0; - CCR.c = CCR.x; - return CCR.z; - } - // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用 - uint64 data64 = data; - uint64 rot = data64 & ((1 << (count - 1)) - 1); - uint32 x = CCR.x & 1; - CCR.z = (data64 >> count) | (rot << (33 - count)) | (x << (32 - count)); - CCR.c = CCR.x = data64 >> (count - 1); - CCR.n = CCR.z; - CCR.v = 0; - return CCR.z; -} - -// data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_ror_8(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_8(cpu, data); - return data; - } - - count %= 8; - uint8 tmp = (data >> count) | (data << (8 - count)); - CCR.z = tmp; - CCR.n = (uint32)tmp << 24; - // 7 0 1 2 3 4 5 6 - CCR.c = data >> ((count + 7) % 8); - CCR.v = 0; - return tmp; -} - -// data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_ror_16(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_16(cpu, data); - return data; - } - - count %= 16; - uint16 tmp = (data >> count) | (data << (16 - count)); - CCR.z = tmp; - CCR.n = (uint32)tmp << 16; - CCR.c = data >> ((count + 15) % 16); - CCR.v = 0; - return tmp; -} - -// data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。 -// count は 0..63 -static inline uint32 -acc_ror_32(m68kcpu *cpu, uint32 data, int count) -{ - if (count == 0) { - acc_move_32(cpu, data); - return data; - } - - count %= 32; - uint64 data64 = (uint64)data; - uint64 tmp = (data >> count) | (data << (32 - count)); - CCR.z = tmp; - CCR.n = tmp; - CCR.c = data64 >> ((count + 31) % 32); - CCR.v = 0; - return tmp; -}