File:  [Isaki's NoNo m68k/m88k emulator] / nono / m680x0 / m680x0acc.cpp
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:48 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, HEAD
nono 1.5.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

#include "mpu680x0.h"
#include "m680x0acc.h"

/*static*/ inline uint32
m680x0ACC::vflag_add_8(uint32 src, uint32 dst, uint32 res)
{
	return vflag_add_32(src, dst, res) << 24;
}

/*static*/ inline uint32
m680x0ACC::vflag_add_16(uint32 src, uint32 dst, uint32 res)
{
	return vflag_add_32(src, dst, res) << 16;
}

/*static*/ inline uint32
m680x0ACC::vflag_add_32(uint32 src, uint32 dst, uint32 res)
{
	return (src ^ res) & (dst ^ res);
}

// src + dst を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::add_8(uint32 src, uint32 dst)
{
	Z = dst + src;
	C = Z >> 8;
	X = C;
	N = Z << 24;
	Z &= 0xff;
	V = vflag_add_8(src, dst, Z);
	return Z;
}

// src + dst を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::add_16(uint32 src, uint32 dst)
{
	Z = dst + src;
	C = Z >> 16;
	X = C;
	N = Z << 16;
	Z &= 0xffff;
	V = vflag_add_16(src, dst, Z);
	return Z;
}

// src + dst を計算し、XNZVC フラグをセットして結果を返す。
uint32
m680x0ACC::add_32(uint32 src, uint32 dst)
{
	CZ = (uint64)dst + (uint64)src;
	X = C;
	V = vflag_add_32(src, dst, Z);
	N = Z;
	return Z;
}

// src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::addx_8(uint32 src, uint32 dst)
{
	uint32 res = dst + src + (IsX() ? 1 : 0);
	C = res >> 8;
	X = C;
	N = res << 24;
	// 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
	if (N != 0) {
		Z = N;
	}
	V = vflag_add_8(src, dst, res);
	return res & 0xff;
}

// src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::addx_16(uint32 src, uint32 dst)
{
	uint32 res = dst + src + (IsX() ? 1 : 0);
	C = res >> 16;
	X = C;
	N = res << 16;
	// 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
	if (N != 0) {
		Z = N;
	}
	V = vflag_add_16(src, dst, res);
	return res & 0xffff;
}

// src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
uint32
m680x0ACC::addx_32(uint32 src, uint32 dst)
{
	uint64 res = (uint64)dst + (uint64)src + (IsX() ? 1 : 0);
	C = res >> 32;
	X = C;
	N = res;
	// 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
	if (N != 0) {
		Z = N;
	}
	V = vflag_add_32(src, dst, res);
	return res;
}


/*static*/ inline uint32
m680x0ACC::vflag_sub_8(uint32 src, uint32 dst, uint32 res)
{
	return vflag_sub_32(src, dst, res) << 24;
}

/*static*/ inline uint32
m680x0ACC::vflag_sub_16(uint32 src, uint32 dst, uint32 res)
{
	return vflag_sub_32(src, dst, res) << 16;
}

/*static*/ inline uint32
m680x0ACC::vflag_sub_32(uint32 src, uint32 dst, uint32 res)
{
	return (src ^ dst) & (dst ^ res);
}

// dst - src を計算し、NZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::cmp_8(uint32 src, uint32 dst)
{
	Z = dst - src;
	C = Z >> 8;
	N = Z << 24;
	Z &= 0xff;
	V = vflag_sub_8(src, dst, Z);
	return Z;
}

// dst - src を計算し、NZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::cmp_16(uint32 src, uint32 dst)
{
	Z = dst - src;
	C = Z >> 16;
	N = Z << 16;
	Z &= 0xffff;
	V = vflag_sub_16(src, dst, Z);
	return Z;
}

// dst - src を計算し、NZVC フラグをセットして結果を返す。
uint32
m680x0ACC::cmp_32(uint32 src, uint32 dst)
{
	CZ = (uint64)dst - (uint64)src;
	N = Z;
	V = vflag_sub_32(src, dst, Z);
	return Z;
}

// dst - src を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::sub_8(uint32 src, uint32 dst)
{
	uint32 res = cmp_8(src, dst);
	X = C;
	return res;
}

// dst - src を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::sub_16(uint32 src, uint32 dst)
{
	uint32 res = cmp_16(src, dst);
	X = C;
	return res;
}

// dst - src を計算し、XNZVC フラグをセットして結果を返す。
uint32
m680x0ACC::sub_32(uint32 src, uint32 dst)
{
	uint32 res = cmp_32(src, dst);
	X = C;
	return res;
}

// src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値 res の上位ビットはクリアされている。
uint32
m680x0ACC::subx_8(uint32 src, uint32 dst)
{
	uint32 res = dst - src - (IsX() ? 1 : 0);
	C = res >> 8;
	X = C;
	N = res << 24;
	// 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
	if (N != 0) {
		Z = N;
	}
	V = vflag_sub_8(src, dst, res);
	return res & 0xff;
}

// src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値 res の上位ビットはクリアされている。
uint32
m680x0ACC::subx_16(uint32 src, uint32 dst)
{
	uint32 res = dst - src - (IsX() ? 1 : 0);
	C = res >> 16;
	X = C;
	N = res << 16;
	// 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
	if (N != 0) {
		Z = N;
	}
	V = vflag_sub_16(src, dst, res);
	return res & 0xffff;
}

// src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
uint32
m680x0ACC::subx_32(uint32 src, uint32 dst)
{
	uint64 res = (uint64)dst - (uint64)src - (IsX() ? 1 : 0);
	C = res >> 32;
	X = C;
	N = res;
	// 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
	if (N != 0) {
		Z = N;
	}
	V = vflag_sub_32(src, dst, res);
	return res;
}

// src(u16) * dst(u16) を計算し、NZVC フラグをセットして結果(u32)を返す。
// src, dst の上位ビットはクリアしておくこと。
uint32
m680x0ACC::mulu_16(uint32 src, uint32 dst)
{
	uint32 res = src * dst;
	// 16x16->32 ではオーバーフローは起きないので move でよい
	move_32(res);
	return res;
}

// src(s16) * dst(s16) を計算し、NZVC フラグをセットして結果(u32)を返す。
// src, dst の上位ビットはクリアしておくこと。
uint32
m680x0ACC::muls_16(uint32 src, uint32 dst)
{
	int32 res = (int32)(int16)src * (int32)(int16)dst;
	// 16x16->32 ではオーバーフローは起きないので move でよい
	move_32(res);
	return res;
}

// src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
uint32
m680x0ACC::mulu_32(uint32 src, uint32 dst)
{
	uint64 res = (uint64)src * (uint64)dst;
	Z = res;
	N = res;
	C = 0;
	if (res > 0xffffffffUL) {
		V = V_BIT;
	} else {
		V = 0;
	}
	return (uint32)res;
}

// src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
uint32
m680x0ACC::muls_32(uint32 src, uint32 dst)
{
	int64 res = (int64)(int32)src * (int64)(int32)dst;
	Z = res;
	N = res;
	C = 0;
	// V フラグは64ビット演算結果の上位32ビットが
	// 下位32ビットの符号拡張になっていなかった場合に立つ。
	// つまり符号付き整数で 32bit 表現と 64bit 表現が一致していなければ立つ。
	int32 tmp = res;
	if (res != tmp) {
		V = V_BIT;
	} else {
		V = 0;
	}
	return (uint32)res;
}

// src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
uint64
m680x0ACC::mulu_64(uint32 src, uint32 dst)
{
	uint64 res = (uint64)src * (uint64)dst;
	N = res >> 32;
	Z = N | res;
	V = 0;
	C = 0;
	return res;
}

// src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
uint64
m680x0ACC::muls_64(uint32 src, uint32 dst)
{
	int64 res = (int64)(int32)src * (int64)(int32)dst;
	N = res >> 32;
	Z = N | res;
	V = 0;
	C = 0;
	return res;
}

void
m680x0ACC::btst(uint32 data, int n)
{
	Z = data & (1U << n);
}

uint32
m680x0ACC::bchg(uint32 data, int n)
{
	Z = data & (1U << n);
	data ^= (1U << n);
	return data;
}

uint32
m680x0ACC::bclr(uint32 data, int n)
{
	Z = data & (1U << n);
	data &= ~(1U << n);
	return data;
}

uint32
m680x0ACC::bset(uint32 data, int n)
{
	Z = data & (1U << n);
	data |= (1U << n);
	return data;
}


// data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..63。data の上位はクリアしておくこと。
uint32
m680x0ACC::asl_8(uint32 data, int count)
{
	if (count == 0) {
		move_8(data);
		return data;
	}
	int64 tmps = (int64)(int8)data;
	if (count > 8) count = 9;
	uint64 tmp = (uint64)tmps << count;
	X = C = tmp >> 8;
	N = tmp << 24;
	Z = N;
	// 送り出された全てのビットが元の MSB と一致すれば V=0
	SetV(((int64)tmp >> 7) != (tmps >> 8));
	return tmp & 0xff;
}

// data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..63。data の上位はクリアしておくこと。
uint32
m680x0ACC::asl_16(uint32 data, int count)
{
	if (count == 0) {
		move_16(data);
		return data;
	}
	int64 tmps = (int64)(int16)data;
	if (count > 16) count = 17;
	uint64 tmp = (uint64)tmps << count;
	X = C = tmp >> 16;
	N = tmp << 16;
	Z = N;
	// 送り出された全てのビットが元の MSB と一致すれば V=0
	SetV(((int64)tmp >> 15) != (tmps >> 16));
	return tmp & 0xffff;
}

// data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::asl_32(uint32 data, int count)
{
	if (count == 0) {
		move_32(data);
		return data;
	}
	int64 tmps = (int64)(int32)data;
	if (count > 32) count = 33;
	uint64 tmp = (uint64)tmps << count;
	X = C = tmp >> 32;
	N = Z = tmp;
	// 送り出された全てのビットが元の MSB と一致すれば V=0
	SetV(((int64)tmp >> 31) != (tmps >> 32));
	return tmp;
}

// data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
// count は 0..63。data の上位はクリアしておくこと。
uint32
m680x0ACC::lsl_8(uint32 data, int count)
{
	if (count == 0) {
		move_8(data);
		return data;
	}
	uint64 tmp = (uint64)data << count;
	X = C = tmp >> 8;
	N = tmp << 24;
	Z = tmp & 0xff;
	V = 0;
	return Z;
}

// data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
// count は 0..63。data の上位はクリアしておくこと。
uint32
m680x0ACC::lsl_16(uint32 data, int count)
{
	if (count == 0) {
		move_16(data);
		return data;
	}
	uint64 tmp = (uint64)data << count;
	X = C = tmp >> 16;
	N = tmp << 16;
	Z = tmp & 0xffff;
	V = 0;
	return Z;
}

// data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::lsl_32(uint32 data, int count)
{
	if (count == 0) {
		move_32(data);
		return data;
	}
	uint64 tmp = (uint64)data << count;
	X = C = tmp >> 32;
	N = tmp;
	Z = tmp;
	V = 0;
	return Z;
}

// data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::roxl_8(uint32 data, int count)
{
	count %= 9;
	if (count == 0) {
		Z = data;
		N = data << 24;
		V = 0;
		C = X;
		return Z;
	}
	uint32 xbit = X & 1;
	Z = (data << count) | (data >> (9 - count)) | (xbit << (count - 1));
	C = X = Z >> 8;
	Z &= 0xff;
	N = Z << 24;
	V = 0;
	return Z;
}

// data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::roxl_16(uint32 data, int count)
{
	count %= 17;
	if (count == 0) {
		Z = data;
		N = data << 16;
		V = 0;
		C = X;
		return Z;
	}
	uint32 xbit = X & 1;
	Z = (data << count) | (data >> (17 - count)) | (xbit << (count - 1));
	C = X = Z >> 16;
	Z &= 0xffff;
	N = Z << 16;
	V = 0;
	return Z;
}

// data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::roxl_32(uint32 data, int count)
{
	count %= 33;
	if (count == 0) {
		Z = data;
		N = data;
		V = 0;
		C = X;
		return Z;
	}
	// 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
	uint64 data64 = data;
	uint32 xbit = X & 1;
	Z = (data64 << count) | (data64 >> (33 - count)) | (xbit << (count - 1));
	C = X = data64 >> (32 - count);
	N = Z;
	V = 0;
	return Z;
}

// data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63。data の上位はクリアしておくこと
uint32
m680x0ACC::rol_8(uint32 data, int count)
{
	if (count == 0) {
		move_8(data);
		return data;
	}

	count %= 8;
	int count2 = (8 - count) % 8;
	uint8 tmp = (data << count) | (data >> count2);
	Z = tmp;
	N = (uint32)tmp << 24;
	C = data >> count2;
	V = 0;
	return Z;
}

// data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63。data の上位はクリアしておくこと
uint32
m680x0ACC::rol_16(uint32 data, int count)
{
	if (count == 0) {
		move_16(data);
		return data;
	}

	count %= 16;
	int count2 = (16 - count) % 16;
	uint16 tmp = (data << count) | (data >> count2);
	Z = tmp;
	N = (uint32)tmp << 16;
	C = data >> count2;
	V = 0;
	return Z;
}

// data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::rol_32(uint32 data, int count)
{
	if (count == 0) {
		move_32(data);
		return data;
	}

	count %= 32;
	int count2 = (32 - count) % 32;
	uint64 data64 = (uint64)data;
	uint64 tmp = (data << count) | (data >> count2);
	Z = tmp;
	N = Z;
	C = data64 >> count2;
	V = 0;
	return Z;
}

// data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..64。data の上位はクリアしておくこと。
uint32
m680x0ACC::asr_8(uint32 data, int count)
{
	if (count == 0) {
		move_8(data);
		return data;
	}
	if (count > 8) {
		if ((int8)data < 0) {
			data = 0xff;
		} else {
			data = 0;
		}
		X = C = Z = data;
		N = data << 24;
		V = 0;
		return data;
	}
	// data >>> count の結果が tmp の上位32ビット中の下位8ビットに入る
	uint64 tmp = (uint64)(int64)(int8)data << (32 - count);
	X = C = tmp >> 31;
	N = tmp >> 8;
	Z = (tmp >> 32) & 0xff;
	V = 0;
	return Z;
}

// data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..64。data の上位はクリアしておくこと。
uint32
m680x0ACC::asr_16(uint32 data, int count)
{
	if (count == 0) {
		move_16(data);
		return data;
	}
	if (count > 16) {
		if ((int16)data < 0) {
			data = 0xffff;
		} else {
			data = 0;
		}
		X = C = Z = data;
		N = data << 16;
		V = 0;
		return data;
	}
	// data >>> count の結果が tmp の上位32ビット中の下位16ビットに入る
	uint64 tmp = (uint64)(int64)(int16)data << (32 - count);
	X = C = tmp >> 31;
	N = tmp >> 16;
	Z = (tmp >> 32) & 0xffff;
	V = 0;
	return Z;
}

// data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..64
uint32
m680x0ACC::asr_32(uint32 data, int count)
{
	if (count == 0) {
		move_32(data);
		return data;
	}
	if (count > 32) {
		if ((int32)data < 0) {
			data = 0xffffffff;
		} else {
			data = 0;
		}
		X = C = Z = data;
		N = data;
		V = 0;
		return data;
	}
	// data >>> count の結果が tmp の上位32ビットに入る
	uint64 tmp = (uint64)(int64)(int32)data << (32 - count);
	X = C = tmp >> 31;
	Z = N = tmp >> 32;
	V = 0;
	return Z;
}

// data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::lsr_8(uint32 data, int count)
{
	if (count == 0) {
		move_8(data);
		return data;
	}
	if (count > 8) {
		X = C = 0;
		move_8(0);
		return 0;
	}
	// data >> count の結果が tmp の上位32ビットに入る
	uint64 tmp = (uint64)data << (32 - count);
	X = C = tmp >> 31;
	N = tmp >> 8;
	Z = (tmp >> 32) & 0xff;
	V = 0;
	return Z;
}

// data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::lsr_16(uint32 data, int count)
{
	if (count == 0) {
		move_16(data);
		return data;
	}
	if (count > 16) {
		X = C = 0;
		move_16(0);
		return 0;
	}
	// data >> count の結果が tmp の上位32ビットに入る
	uint64 tmp = (uint64)data << (32 - count);
	X = C = tmp >> 31;
	N = tmp >> 16;
	Z = (tmp >> 32) & 0xffff;
	V = 0;
	return Z;
}

// data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::lsr_32(uint32 data, int count)
{
	if (count == 0) {
		move_32(data);
		return data;
	}
	if (count > 32) {
		X = C = 0;
		move_32(0);
		return 0;
	}
	// data >> count の結果が tmp の上位32ビットに入る
	uint64 tmp = (uint64)data << (32 - count);
	X = C = tmp >> 31;
	Z = N = tmp >> 32;
	V = 0;
	return Z;
}

// data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::roxr_8(uint32 data, int count)
{
	count %= 9;
	if (count == 0) {
		Z = data;
		N = data << 24;
		V = 0;
		C = X;
		return Z;
	}
	uint32 rot = data & ((1U << (count - 1)) - 1);
	uint32 xbit = X & 1;
	Z = (data >> count) | (rot << (9 - count)) | (xbit << (8 - count));
	C = X = data >> (count - 1);
	N = Z << 24;
	V = 0;
	return Z;
}

// data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::roxr_16(uint32 data, int count)
{
	count %= 17;
	if (count == 0) {
		Z = data;
		N = data << 16;
		V = 0;
		C = X;
		return Z;
	}
	uint32 rot = data & ((1U << (count - 1)) - 1);
	uint32 xbit = X & 1;
	Z = (data >> count) | (rot << (17 - count)) | (xbit << (16 - count));
	C = X = data >> (count - 1);
	N = Z << 16;
	V = 0;
	return Z;
}

// data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::roxr_32(uint32 data, int count)
{
	count %= 33;
	if (count == 0) {
		Z = data;
		N = data;
		V = 0;
		C = X;
		return Z;
	}
	// 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
	uint64 data64 = data;
	uint64 rot = data64 & ((1U << (count - 1)) - 1);
	uint32 xbit = X & 1;
	Z = (data64 >> count) | (rot << (33 - count)) | (xbit << (32 - count));
	C = X = data64 >> (count - 1);
	N = Z;
	V = 0;
	return Z;
}

// data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::ror_8(uint32 data, int count)
{
	if (count == 0) {
		move_8(data);
		return data;
	}

	count %= 8;
	uint8 tmp = (data >> count) | (data << (8 - count));
	Z = tmp;
	N = (uint32)tmp << 24;
	// 7 0 1 2 3 4 5 6
	C = data >> ((count + 7) % 8);
	V = 0;
	return tmp;
}

// data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::ror_16(uint32 data, int count)
{
	if (count == 0) {
		move_16(data);
		return data;
	}

	count %= 16;
	uint16 tmp = (data >> count) | (data << (16 - count));
	Z = tmp;
	N = (uint32)tmp << 16;
	C = data >> ((count + 15) % 16);
	V = 0;
	return tmp;
}

// data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
// count は 0..63
uint32
m680x0ACC::ror_32(uint32 data, int count)
{
	if (count == 0) {
		move_32(data);
		return data;
	}

	count %= 32;
	uint64 data64 = (uint64)data;
	uint64 tmp = (data >> count) | (data << (32 - count));
	Z = tmp;
	N = tmp;
	C = data64 >> ((count + 31) % 32);
	V = 0;
	return tmp;
}

void
m680x0ACC::chk2cmp2_32(uint32 compare, uint32 lower, uint32 upper)
{
	// 実機の実行結果をじっと睨んだ結果、このロジックで
	// cmp2 は実行していると考えられる。
	// オペランド順はフラグに影響する。
	// なぜ 68k のデザイナが順序を入れ替えたのかは不明。
	// なんかの都合があったんだろうな...

	// この cmp は通常の if で代替できるけど、
	// あえて MPU 内部の動作をエミュレート。
	cmp_32(lower, upper);

	if (CondCS()) {
		cmp_32(compare, upper);
		if (CondEQ()) {
			// break
		} else if (CondCS()) {
			cmp_32(lower, compare);
		} else {
			cmp_32(compare, lower);
		}
	} else {
		cmp_32(lower, compare);
		if (CondEQ()) {
			// break
		} else if (CondCS()) {
			// break
		} else {
			cmp_32(compare, upper);
		}
	}
}

// src_10 + dst_10 + X を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::abcd_8(uint32 src, uint32 dst)
{
	uint32 res;
	uint32 tmp;
	uint32 adj;
	uint32 low;
	uint32 cbit;

	adj = 0;
	cbit = 0;

	// X フラグは LSB なので直接足してよい
	tmp = src + dst + (X & X_BIT);

	low = (src & 0x0f) + (dst & 0x0f) + (X & X_BIT);
	if (low > 0x09) {
		adj = 0x06;
	}

	if (tmp > 0x99) {
		adj += 0x60;
		cbit = C_BIT;
	}

	res = tmp + adj;
	cbit |= res >> 8;
	X = C = cbit;

	res &= 0xff;
	Z |= res;

	// V フラグは不定だが 68030 では常にクリア
	V = 0;
	// N フラグは不定だが 68030 実機合わせ
	N = res << 24;

	return res;
}

// src_10 - dst_10 - X を計算し、XNZVC フラグをセットして結果を返す。
// src, dst の上位ビットはクリアしておくこと。
// 戻り値の上位ビットはクリアされている。
uint32
m680x0ACC::sbcd_8(uint32 src, uint32 dst)
{
	uint32 res;
	int32 tmp;
	int32 adj;
	int32 low;
	uint32 cbit;

	adj = 0;
	cbit = 0;

	// X フラグは LSB なので直接引いてよい
	tmp = dst - src - (X & X_BIT);

	low = (dst & 0x0f) - (src & 0x0f) - (X & X_BIT);
	if (low < 0) {
		adj = 0x06;
	}

	if (tmp < 0) {
		adj += 0x60;
		cbit = C_BIT;
	}

	res = tmp - adj;
	cbit |= res >> 8;
	X = C = cbit;

	res &= 0xff;
	Z |= res;

	// V フラグは不定だが 68030 では常にクリア
	V = 0;
	// N フラグは不定だが 68030 実機合わせ
	N = res << 24;

	return res;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.