|
|
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;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.