mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Name flags, remove closing underscores on exposed data fields.
This commit is contained in:
parent
bd61c72007
commit
f3c1b1f052
@ -43,7 +43,7 @@ void Executor<model, BusHandler>::reset_processor() {
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT>
|
||||
IntT Executor<model, BusHandler>::read(uint32_t address, bool is_from_pc) {
|
||||
const auto code = FunctionCode((status_.is_supervisor_ << 2) | 1 << int(is_from_pc));
|
||||
const auto code = FunctionCode((status_.is_supervisor << 2) | 1 << int(is_from_pc));
|
||||
if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) {
|
||||
throw AccessException(code, address, Exception::AddressError | (int(is_from_pc) << 3) | (1 << 4));
|
||||
}
|
||||
@ -55,7 +55,7 @@ IntT Executor<model, BusHandler>::read(uint32_t address, bool is_from_pc) {
|
||||
template <Model model, typename BusHandler>
|
||||
template <typename IntT>
|
||||
void Executor<model, BusHandler>::write(uint32_t address, IntT value) {
|
||||
const auto code = FunctionCode((status_.is_supervisor_ << 2) | 1);
|
||||
const auto code = FunctionCode((status_.is_supervisor << 2) | 1);
|
||||
if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) {
|
||||
throw AccessException(code, address, Exception::AddressError);
|
||||
}
|
||||
@ -240,8 +240,8 @@ void Executor<model, BusHandler>::run_for_instructions(int count) {
|
||||
|
||||
// Grab the status to store, then switch into supervisor mode.
|
||||
const uint16_t status = status_.status();
|
||||
status_.is_supervisor_ = 1;
|
||||
status_.trace_flag_ = 0;
|
||||
status_.is_supervisor = 1;
|
||||
status_.trace_flag = 0;
|
||||
did_update_status();
|
||||
|
||||
// Push status and the program counter at instruction start.
|
||||
@ -271,14 +271,14 @@ void Executor<model, BusHandler>::run(int &count) {
|
||||
|
||||
// Capture the trace bit, indicating whether to trace
|
||||
// after this instruction.
|
||||
const auto should_trace = status_.trace_flag_;
|
||||
const auto should_trace = status_.trace_flag;
|
||||
|
||||
// Read the next instruction.
|
||||
instruction_address_ = program_counter_.l;
|
||||
instruction_opcode_ = read_pc<uint16_t>();
|
||||
const Preinstruction instruction = decoder_.decode(instruction_opcode_);
|
||||
|
||||
if(!status_.is_supervisor_ && instruction.requires_supervisor()) {
|
||||
if(!status_.is_supervisor && instruction.requires_supervisor()) {
|
||||
raise_exception(Exception::PrivilegeViolation);
|
||||
continue;
|
||||
}
|
||||
@ -369,7 +369,7 @@ typename Executor<model, BusHandler>::Registers Executor<model, BusHandler>::get
|
||||
result.status = status_.status();
|
||||
result.program_counter = program_counter_.l;
|
||||
|
||||
stack_pointers_[status_.is_supervisor_] = sp;
|
||||
stack_pointers_[status_.is_supervisor] = sp;
|
||||
result.user_stack_pointer = stack_pointers_[0].l;
|
||||
result.supervisor_stack_pointer = stack_pointers_[1].l;
|
||||
|
||||
@ -389,7 +389,7 @@ void Executor<model, BusHandler>::set_state(const Registers &state) {
|
||||
|
||||
stack_pointers_[0].l = state.user_stack_pointer;
|
||||
stack_pointers_[1].l = state.supervisor_stack_pointer;
|
||||
sp = stack_pointers_[status_.is_supervisor_];
|
||||
sp = stack_pointers_[status_.is_supervisor];
|
||||
}
|
||||
|
||||
// MARK: - Flow Control.
|
||||
@ -402,8 +402,8 @@ void Executor<model, BusHandler>::raise_exception(int index) {
|
||||
// Grab the status to store, then switch into supervisor mode
|
||||
// and disable tracing.
|
||||
const uint16_t status = status_.status();
|
||||
status_.is_supervisor_ = 1;
|
||||
status_.trace_flag_ = 0;
|
||||
status_.is_supervisor = 1;
|
||||
status_.trace_flag = 0;
|
||||
did_update_status();
|
||||
|
||||
// Push status and the program counter at instruction start.
|
||||
@ -419,8 +419,8 @@ template <Model model, typename BusHandler>
|
||||
void Executor<model, BusHandler>::did_update_status() {
|
||||
// Shuffle the stack pointers.
|
||||
stack_pointers_[active_stack_pointer_] = sp;
|
||||
sp = stack_pointers_[status_.is_supervisor_];
|
||||
active_stack_pointer_ = status_.is_supervisor_;
|
||||
sp = stack_pointers_[status_.is_supervisor];
|
||||
active_stack_pointer_ = status_.is_supervisor;
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
@ -518,9 +518,9 @@ void Executor<model, BusHandler>::tas(Preinstruction instruction, uint32_t addre
|
||||
Dn(instruction.reg<0>()).b = uint8_t(address | 0x80);
|
||||
}
|
||||
|
||||
status_.overflow_flag_ = status_.carry_flag_ = 0;
|
||||
status_.zero_result_ = value;
|
||||
status_.negative_flag_ = value & 0x80;
|
||||
status_.overflow_flag = status_.carry_flag = 0;
|
||||
status_.zero_result = value;
|
||||
status_.negative_flag = value & 0x80;
|
||||
}
|
||||
|
||||
template <Model model, typename BusHandler>
|
||||
|
@ -39,17 +39,17 @@ template <
|
||||
const uint8_t destination = dest.b;
|
||||
|
||||
// Perform the BCD add by evaluating the two nibbles separately.
|
||||
const int unadjusted_result = destination + source + (status.extend_flag_ ? 1 : 0);
|
||||
int result = (destination & 0xf) + (source & 0xf) + (status.extend_flag_ ? 1 : 0);
|
||||
const int unadjusted_result = destination + source + (status.extend_flag ? 1 : 0);
|
||||
int result = (destination & 0xf) + (source & 0xf) + (status.extend_flag ? 1 : 0);
|
||||
if(result > 0x09) result += 0x06;
|
||||
result += (destination & 0xf0) + (source & 0xf0);
|
||||
if(result > 0x9f) result += 0x60;
|
||||
|
||||
// Set all flags essentially as if this were normal addition.
|
||||
status.zero_result_ |= result & 0xff;
|
||||
status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result & ~0xff);
|
||||
status.negative_flag_ = result & 0x80;
|
||||
status.overflow_flag_ = ~unadjusted_result & result & 0x80;
|
||||
status.zero_result |= result & 0xff;
|
||||
status.extend_flag = status.carry_flag = uint_fast32_t(result & ~0xff);
|
||||
status.negative_flag = result & 0x80;
|
||||
status.overflow_flag = ~unadjusted_result & result & 0x80;
|
||||
|
||||
// Store the result.
|
||||
dest.b = uint8_t(result);
|
||||
@ -66,10 +66,10 @@ template <
|
||||
const auto result = op(destination, source, x); \
|
||||
\
|
||||
b = uint8_t(result); \
|
||||
zero_op(status.zero_result_, b); \
|
||||
status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result & ~0xff); \
|
||||
status.negative_flag_ = result & 0x80; \
|
||||
status.overflow_flag_ = overflow() & 0x80;
|
||||
zero_op(status.zero_result, b); \
|
||||
status.extend_flag = status.carry_flag = uint_fast32_t(result & ~0xff); \
|
||||
status.negative_flag = result & 0x80; \
|
||||
status.overflow_flag = overflow() & 0x80;
|
||||
|
||||
#define addsubw(a, b, op, overflow, x, zero_op) \
|
||||
const int source = a; \
|
||||
@ -77,10 +77,10 @@ template <
|
||||
const auto result = op(destination, source, x); \
|
||||
\
|
||||
b = uint16_t(result); \
|
||||
zero_op(status.zero_result_, b); \
|
||||
status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result & ~0xffff); \
|
||||
status.negative_flag_ = result & 0x8000; \
|
||||
status.overflow_flag_ = overflow() & 0x8000;
|
||||
zero_op(status.zero_result, b); \
|
||||
status.extend_flag = status.carry_flag = uint_fast32_t(result & ~0xffff); \
|
||||
status.negative_flag = result & 0x8000; \
|
||||
status.overflow_flag = overflow() & 0x8000;
|
||||
|
||||
#define addsubl(a, b, op, overflow, x, zero_op) \
|
||||
const uint64_t source = a; \
|
||||
@ -88,10 +88,10 @@ template <
|
||||
const auto result = op(destination, source, x); \
|
||||
\
|
||||
b = uint32_t(result); \
|
||||
zero_op(status.zero_result_, b); \
|
||||
status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result >> 32); \
|
||||
status.negative_flag_ = result & 0x80000000; \
|
||||
status.overflow_flag_ = overflow() & 0x80000000;
|
||||
zero_op(status.zero_result, b); \
|
||||
status.extend_flag = status.carry_flag = uint_fast32_t(result >> 32); \
|
||||
status.negative_flag = result & 0x80000000; \
|
||||
status.overflow_flag = overflow() & 0x80000000;
|
||||
|
||||
#define addb(a, b, x, z) addsubb(a, b, addop, add_overflow, x, z)
|
||||
#define subb(a, b, x, z) addsubb(a, b, subop, sub_overflow, x, z)
|
||||
@ -101,7 +101,7 @@ template <
|
||||
#define subl(a, b, x, z) addsubl(a, b, subop, sub_overflow, x, z)
|
||||
|
||||
#define no_extend(op, a, b) op(a, b, 0, z_set)
|
||||
#define extend(op, a, b) op(a, b, status.extend_flag_, z_or)
|
||||
#define extend(op, a, b) op(a, b, status.extend_flag, z_or)
|
||||
|
||||
// ADD and ADDA add two quantities, the latter sign extending and without setting any flags;
|
||||
// ADDQ and SUBQ act as ADD and SUB, but taking the second argument from the instruction code.
|
||||
@ -212,13 +212,13 @@ template <
|
||||
// BTST/BCLR/etc: modulo for the mask depends on whether memory or a data register is the target.
|
||||
case Operation::BTST: {
|
||||
const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7;
|
||||
status.zero_result_ = dest.l & (1 << (src.l & mask));
|
||||
status.zero_result = dest.l & (1 << (src.l & mask));
|
||||
} break;
|
||||
|
||||
case Operation::BCLR: {
|
||||
const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7;
|
||||
|
||||
status.zero_result_ = dest.l & (1 << (src.l & mask));
|
||||
status.zero_result = dest.l & (1 << (src.l & mask));
|
||||
dest.l &= ~(1 << (src.l & mask));
|
||||
flow_controller.did_bit_op(src.l & mask);
|
||||
} break;
|
||||
@ -226,7 +226,7 @@ template <
|
||||
case Operation::BCHG: {
|
||||
const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7;
|
||||
|
||||
status.zero_result_ = dest.l & (1 << (src.l & mask));
|
||||
status.zero_result = dest.l & (1 << (src.l & mask));
|
||||
dest.l ^= 1 << (src.l & mask);
|
||||
flow_controller.did_bit_op(src.l & mask);
|
||||
} break;
|
||||
@ -234,7 +234,7 @@ template <
|
||||
case Operation::BSET: {
|
||||
const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7;
|
||||
|
||||
status.zero_result_ = dest.l & (1 << (src.l & mask));
|
||||
status.zero_result = dest.l & (1 << (src.l & mask));
|
||||
dest.l |= 1 << (src.l & mask);
|
||||
flow_controller.did_bit_op(src.l & mask);
|
||||
} break;
|
||||
@ -294,17 +294,17 @@ template <
|
||||
*/
|
||||
case Operation::CLRb:
|
||||
src.b = 0;
|
||||
status.negative_flag_ = status.overflow_flag_ = status.carry_flag_ = status.zero_result_ = 0;
|
||||
status.negative_flag = status.overflow_flag = status.carry_flag = status.zero_result = 0;
|
||||
break;
|
||||
|
||||
case Operation::CLRw:
|
||||
src.w = 0;
|
||||
status.negative_flag_ = status.overflow_flag_ = status.carry_flag_ = status.zero_result_ = 0;
|
||||
status.negative_flag = status.overflow_flag = status.carry_flag = status.zero_result = 0;
|
||||
break;
|
||||
|
||||
case Operation::CLRl:
|
||||
src.l = 0;
|
||||
status.negative_flag_ = status.overflow_flag_ = status.carry_flag_ = status.zero_result_ = 0;
|
||||
status.negative_flag = status.overflow_flag = status.carry_flag = status.zero_result = 0;
|
||||
break;
|
||||
|
||||
/*
|
||||
@ -316,10 +316,10 @@ template <
|
||||
const uint8_t destination = dest.b;
|
||||
const int result = destination - source;
|
||||
|
||||
status.zero_result_ = result & 0xff;
|
||||
status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xff);
|
||||
status.negative_flag_ = result & 0x80;
|
||||
status.overflow_flag_ = sub_overflow() & 0x80;
|
||||
status.zero_result = result & 0xff;
|
||||
status.carry_flag = decltype(status.carry_flag)(result & ~0xff);
|
||||
status.negative_flag = result & 0x80;
|
||||
status.overflow_flag = sub_overflow() & 0x80;
|
||||
} break;
|
||||
|
||||
case Operation::CMPw: {
|
||||
@ -327,10 +327,10 @@ template <
|
||||
const uint16_t destination = dest.w;
|
||||
const int result = destination - source;
|
||||
|
||||
status.zero_result_ = result & 0xffff;
|
||||
status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xffff);
|
||||
status.negative_flag_ = result & 0x8000;
|
||||
status.overflow_flag_ = sub_overflow() & 0x8000;
|
||||
status.zero_result = result & 0xffff;
|
||||
status.carry_flag = decltype(status.carry_flag)(result & ~0xffff);
|
||||
status.negative_flag = result & 0x8000;
|
||||
status.overflow_flag = sub_overflow() & 0x8000;
|
||||
} break;
|
||||
|
||||
case Operation::CMPAw: {
|
||||
@ -338,10 +338,10 @@ template <
|
||||
const uint64_t destination = dest.l;
|
||||
const auto result = destination - source;
|
||||
|
||||
status.zero_result_ = uint32_t(result);
|
||||
status.carry_flag_ = result >> 32;
|
||||
status.negative_flag_ = result & 0x80000000;
|
||||
status.overflow_flag_ = sub_overflow() & 0x80000000;
|
||||
status.zero_result = uint32_t(result);
|
||||
status.carry_flag = result >> 32;
|
||||
status.negative_flag = result & 0x80000000;
|
||||
status.overflow_flag = sub_overflow() & 0x80000000;
|
||||
} break;
|
||||
|
||||
// TODO: is there any benefit to keeping both of these?
|
||||
@ -351,10 +351,10 @@ template <
|
||||
const auto destination = uint64_t(dest.l);
|
||||
const auto result = destination - source;
|
||||
|
||||
status.zero_result_ = uint32_t(result);
|
||||
status.carry_flag_ = result >> 32;
|
||||
status.negative_flag_ = result & 0x80000000;
|
||||
status.overflow_flag_ = sub_overflow() & 0x80000000;
|
||||
status.zero_result = uint32_t(result);
|
||||
status.carry_flag = result >> 32;
|
||||
status.negative_flag = result & 0x80000000;
|
||||
status.overflow_flag = sub_overflow() & 0x80000000;
|
||||
} break;
|
||||
|
||||
// JMP: copies EA(0) to the program counter.
|
||||
@ -372,21 +372,21 @@ template <
|
||||
and set negative, zero, overflow and carry as appropriate.
|
||||
*/
|
||||
case Operation::MOVEb:
|
||||
status.zero_result_ = dest.b = src.b;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80;
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result = dest.b = src.b;
|
||||
status.negative_flag = status.zero_result & 0x80;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
break;
|
||||
|
||||
case Operation::MOVEw:
|
||||
status.zero_result_ = dest.w = src.w;
|
||||
status.negative_flag_ = status.zero_result_ & 0x8000;
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result = dest.w = src.w;
|
||||
status.negative_flag = status.zero_result & 0x8000;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
break;
|
||||
|
||||
case Operation::MOVEl:
|
||||
status.zero_result_ = dest.l = src.l;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80000000;
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result = dest.l = src.l;
|
||||
status.negative_flag = status.zero_result & 0x80000000;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
break;
|
||||
|
||||
/*
|
||||
@ -437,16 +437,16 @@ template <
|
||||
|
||||
case Operation::EXTbtow:
|
||||
src.w = uint16_t(int8_t(src.b));
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result_ = src.w;
|
||||
status.negative_flag_ = status.zero_result_ & 0x8000;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
status.zero_result = src.w;
|
||||
status.negative_flag = status.zero_result & 0x8000;
|
||||
break;
|
||||
|
||||
case Operation::EXTwtol:
|
||||
src.l = u_extend16(src.w);
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result_ = src.l;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80000000;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
status.zero_result = src.l;
|
||||
status.negative_flag = status.zero_result & 0x80000000;
|
||||
break;
|
||||
|
||||
#define and_op(a, b) a &= b
|
||||
@ -488,18 +488,18 @@ template <
|
||||
|
||||
case Operation::MULU:
|
||||
dest.l = dest.w * src.w;
|
||||
status.carry_flag_ = status.overflow_flag_ = 0;
|
||||
status.zero_result_ = dest.l;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80000000;
|
||||
status.carry_flag = status.overflow_flag = 0;
|
||||
status.zero_result = dest.l;
|
||||
status.negative_flag = status.zero_result & 0x80000000;
|
||||
flow_controller.did_mulu(src.w);
|
||||
break;
|
||||
|
||||
case Operation::MULS:
|
||||
dest.l =
|
||||
u_extend16(dest.w) * u_extend16(src.w);
|
||||
status.carry_flag_ = status.overflow_flag_ = 0;
|
||||
status.zero_result_ = dest.l;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80000000;
|
||||
status.carry_flag = status.overflow_flag = 0;
|
||||
status.zero_result = dest.l;
|
||||
status.negative_flag = status.zero_result & 0x80000000;
|
||||
flow_controller.did_muls(src.w);
|
||||
break;
|
||||
|
||||
@ -508,12 +508,12 @@ template <
|
||||
*/
|
||||
|
||||
#define announce_divide_by_zero() \
|
||||
status.negative_flag_ = status.overflow_flag_ = 0; \
|
||||
status.zero_result_ = 1; \
|
||||
status.negative_flag = status.overflow_flag = 0; \
|
||||
status.zero_result = 1; \
|
||||
flow_controller.raise_exception(Exception::IntegerDivideByZero)
|
||||
|
||||
case Operation::DIVU: {
|
||||
status.carry_flag_ = 0;
|
||||
status.carry_flag = 0;
|
||||
|
||||
// An attempt to divide by zero schedules an exception.
|
||||
if(!src.w) {
|
||||
@ -528,7 +528,7 @@ template <
|
||||
|
||||
// If overflow would occur, appropriate flags are set and the result is not written back.
|
||||
if(quotient > 65535) {
|
||||
status.overflow_flag_ = status.zero_result_ = status.negative_flag_ = 1;
|
||||
status.overflow_flag = status.zero_result = status.negative_flag = 1;
|
||||
flow_controller.template did_divu<true>(dividend, divisor);
|
||||
return;
|
||||
}
|
||||
@ -536,14 +536,14 @@ template <
|
||||
const uint16_t remainder = uint16_t(dividend % divisor);
|
||||
dest.l = uint32_t((remainder << 16) | uint16_t(quotient));
|
||||
|
||||
status.overflow_flag_ = 0;
|
||||
status.zero_result_ = quotient;
|
||||
status.negative_flag_ = status.zero_result_ & 0x8000;
|
||||
status.overflow_flag = 0;
|
||||
status.zero_result = quotient;
|
||||
status.negative_flag = status.zero_result & 0x8000;
|
||||
flow_controller.template did_divu<false>(dividend, divisor);
|
||||
} break;
|
||||
|
||||
case Operation::DIVS: {
|
||||
status.carry_flag_ = 0;
|
||||
status.carry_flag = 0;
|
||||
|
||||
// An attempt to divide by zero schedules an exception.
|
||||
if(!src.w) {
|
||||
@ -569,7 +569,7 @@ template <
|
||||
// Check for overflow. If it exists, work here is already done.
|
||||
const auto quotient = dividend / divisor;
|
||||
if(quotient > 32767) {
|
||||
status.overflow_flag_ = 1;
|
||||
status.overflow_flag = 1;
|
||||
flow_controller.template did_divs<true>(signed_dividend, signed_divisor);
|
||||
break;
|
||||
}
|
||||
@ -578,9 +578,9 @@ template <
|
||||
const int signed_quotient = result_sign*int(quotient);
|
||||
dest.l = uint32_t((remainder << 16) | uint16_t(signed_quotient));
|
||||
|
||||
status.zero_result_ = decltype(status.zero_result_)(signed_quotient);
|
||||
status.negative_flag_ = status.zero_result_ & 0x8000;
|
||||
status.overflow_flag_ = 0;
|
||||
status.zero_result = decltype(status.zero_result)(signed_quotient);
|
||||
status.negative_flag = status.zero_result & 0x8000;
|
||||
status.overflow_flag = 0;
|
||||
flow_controller.template did_divs<false>(signed_dividend, signed_divisor);
|
||||
} break;
|
||||
|
||||
@ -592,7 +592,7 @@ template <
|
||||
break;
|
||||
|
||||
case Operation::TRAPV: {
|
||||
if(status.overflow_flag_) {
|
||||
if(status.overflow_flag) {
|
||||
flow_controller.template raise_exception<false>(Exception::TRAPV);
|
||||
}
|
||||
} break;
|
||||
@ -601,15 +601,15 @@ template <
|
||||
const bool is_under = s_extend16(dest.w) < 0;
|
||||
const bool is_over = s_extend16(dest.w) > s_extend16(src.w);
|
||||
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result_ = dest.w;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
status.zero_result = dest.w;
|
||||
|
||||
// Test applied for N:
|
||||
//
|
||||
// if Dn < 0, set negative flag;
|
||||
// otherwise, if Dn > <ea>, reset negative flag.
|
||||
if(is_over) status.negative_flag_ = 0;
|
||||
if(is_under) status.negative_flag_ = 1;
|
||||
if(is_over) status.negative_flag = 0;
|
||||
if(is_under) status.negative_flag = 1;
|
||||
|
||||
// No exception is the default course of action; deviate only if an
|
||||
// exception is necessary.
|
||||
@ -633,10 +633,10 @@ template <
|
||||
const auto result = destination - source;
|
||||
src.b = uint8_t(result);
|
||||
|
||||
status.zero_result_ = result & 0xff;
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xff);
|
||||
status.negative_flag_ = result & 0x80;
|
||||
status.overflow_flag_ = sub_overflow() & 0x80;
|
||||
status.zero_result = result & 0xff;
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xff);
|
||||
status.negative_flag = result & 0x80;
|
||||
status.overflow_flag = sub_overflow() & 0x80;
|
||||
} break;
|
||||
|
||||
case Operation::NEGw: {
|
||||
@ -645,10 +645,10 @@ template <
|
||||
const auto result = destination - source;
|
||||
src.w = uint16_t(result);
|
||||
|
||||
status.zero_result_ = result & 0xffff;
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xffff);
|
||||
status.negative_flag_ = result & 0x8000;
|
||||
status.overflow_flag_ = sub_overflow() & 0x8000;
|
||||
status.zero_result = result & 0xffff;
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xffff);
|
||||
status.negative_flag = result & 0x8000;
|
||||
status.overflow_flag = sub_overflow() & 0x8000;
|
||||
} break;
|
||||
|
||||
case Operation::NEGl: {
|
||||
@ -657,10 +657,10 @@ template <
|
||||
const auto result = destination - source;
|
||||
src.l = uint32_t(result);
|
||||
|
||||
status.zero_result_ = uint_fast32_t(result);
|
||||
status.extend_flag_ = status.carry_flag_ = result >> 32;
|
||||
status.negative_flag_ = result & 0x80000000;
|
||||
status.overflow_flag_ = sub_overflow() & 0x80000000;
|
||||
status.zero_result = uint_fast32_t(result);
|
||||
status.extend_flag = status.carry_flag = result >> 32;
|
||||
status.negative_flag = result & 0x80000000;
|
||||
status.overflow_flag = sub_overflow() & 0x80000000;
|
||||
} break;
|
||||
|
||||
/*
|
||||
@ -669,37 +669,37 @@ template <
|
||||
case Operation::NEGXb: {
|
||||
const int source = src.b;
|
||||
const int destination = 0;
|
||||
const auto result = destination - source - (status.extend_flag_ ? 1 : 0);
|
||||
const auto result = destination - source - (status.extend_flag ? 1 : 0);
|
||||
src.b = uint8_t(result);
|
||||
|
||||
status.zero_result_ |= result & 0xff;
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xff);
|
||||
status.negative_flag_ = result & 0x80;
|
||||
status.overflow_flag_ = sub_overflow() & 0x80;
|
||||
status.zero_result |= result & 0xff;
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xff);
|
||||
status.negative_flag = result & 0x80;
|
||||
status.overflow_flag = sub_overflow() & 0x80;
|
||||
} break;
|
||||
|
||||
case Operation::NEGXw: {
|
||||
const int source = src.w;
|
||||
const int destination = 0;
|
||||
const auto result = destination - source - (status.extend_flag_ ? 1 : 0);
|
||||
const auto result = destination - source - (status.extend_flag ? 1 : 0);
|
||||
src.w = uint16_t(result);
|
||||
|
||||
status.zero_result_ |= result & 0xffff;
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xffff);
|
||||
status.negative_flag_ = result & 0x8000;
|
||||
status.overflow_flag_ = sub_overflow() & 0x8000;
|
||||
status.zero_result |= result & 0xffff;
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xffff);
|
||||
status.negative_flag = result & 0x8000;
|
||||
status.overflow_flag = sub_overflow() & 0x8000;
|
||||
} break;
|
||||
|
||||
case Operation::NEGXl: {
|
||||
const uint64_t source = src.l;
|
||||
const uint64_t destination = 0;
|
||||
const auto result = destination - source - (status.extend_flag_ ? 1 : 0);
|
||||
const auto result = destination - source - (status.extend_flag ? 1 : 0);
|
||||
src.l = uint32_t(result);
|
||||
|
||||
status.zero_result_ |= uint_fast32_t(result);
|
||||
status.extend_flag_ = status.carry_flag_ = result >> 32;
|
||||
status.negative_flag_ = result & 0x80000000;
|
||||
status.overflow_flag_ = sub_overflow() & 0x80000000;
|
||||
status.zero_result |= uint_fast32_t(result);
|
||||
status.extend_flag = status.carry_flag = result >> 32;
|
||||
status.negative_flag = result & 0x80000000;
|
||||
status.overflow_flag = sub_overflow() & 0x80000000;
|
||||
} break;
|
||||
|
||||
/*
|
||||
@ -739,9 +739,9 @@ template <
|
||||
|
||||
#define bitwise(source, dest, sign_mask, operator) \
|
||||
operator(dest, source); \
|
||||
status.overflow_flag_ = status.carry_flag_ = 0; \
|
||||
status.zero_result_ = dest; \
|
||||
status.negative_flag_ = dest & sign_mask;
|
||||
status.overflow_flag = status.carry_flag = 0; \
|
||||
status.zero_result = dest; \
|
||||
status.negative_flag = dest & sign_mask;
|
||||
|
||||
#define andx(source, dest, sign_mask) bitwise(source, dest, sign_mask, op_and)
|
||||
#define eorx(source, dest, sign_mask) bitwise(source, dest, sign_mask, op_eor)
|
||||
@ -768,38 +768,38 @@ template <
|
||||
// NOTs: take the logical inverse, affecting the negative and zero flags.
|
||||
case Operation::NOTb:
|
||||
src.b ^= 0xff;
|
||||
status.zero_result_ = src.b;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80;
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result = src.b;
|
||||
status.negative_flag = status.zero_result & 0x80;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
break;
|
||||
|
||||
case Operation::NOTw:
|
||||
src.w ^= 0xffff;
|
||||
status.zero_result_ = src.w;
|
||||
status.negative_flag_ = status.zero_result_ & 0x8000;
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result = src.w;
|
||||
status.negative_flag = status.zero_result & 0x8000;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
break;
|
||||
|
||||
case Operation::NOTl:
|
||||
src.l ^= 0xffffffff;
|
||||
status.zero_result_ = src.l;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80000000;
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result = src.l;
|
||||
status.negative_flag = status.zero_result & 0x80000000;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
break;
|
||||
|
||||
#define sbcd(d) \
|
||||
/* Perform the BCD arithmetic by evaluating the two nibbles separately. */ \
|
||||
const int unadjusted_result = destination - source - (status.extend_flag_ ? 1 : 0); \
|
||||
int result = (destination & 0xf) - (source & 0xf) - (status.extend_flag_ ? 1 : 0); \
|
||||
const int unadjusted_result = destination - source - (status.extend_flag ? 1 : 0); \
|
||||
int result = (destination & 0xf) - (source & 0xf) - (status.extend_flag ? 1 : 0); \
|
||||
if(result & 0xf0) result -= 0x06; \
|
||||
result += (destination & 0xf0) - (source & 0xf0); \
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)((result & 0xff) > 0x9f); \
|
||||
if(unadjusted_result & 0x100) result -= 0x60; \
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(unadjusted_result & 0x300); \
|
||||
if(unadjusted_result & 0x100) result -= 0x60; \
|
||||
\
|
||||
/* Set all flags essentially as if this were normal subtraction. */ \
|
||||
status.zero_result_ |= result & 0xff; \
|
||||
status.negative_flag_ = result & 0x80; \
|
||||
status.overflow_flag_ = unadjusted_result & ~result & 0x80; \
|
||||
status.zero_result |= result & 0xff; \
|
||||
status.negative_flag = result & 0x80; \
|
||||
status.overflow_flag = unadjusted_result & ~result & 0x80; \
|
||||
\
|
||||
/* Store the result. */ \
|
||||
d = uint8_t(result);
|
||||
@ -840,21 +840,21 @@ template <
|
||||
words[0] = words[1];
|
||||
words[1] = temporary;
|
||||
|
||||
status.zero_result_ = src.l;
|
||||
status.negative_flag_ = temporary & 0x8000;
|
||||
status.overflow_flag_ = status.carry_flag_ = 0;
|
||||
status.zero_result = src.l;
|
||||
status.negative_flag = temporary & 0x8000;
|
||||
status.overflow_flag = status.carry_flag = 0;
|
||||
} break;
|
||||
|
||||
/*
|
||||
Shifts and rotates.
|
||||
*/
|
||||
#define set_neg_zero(v, m) \
|
||||
status.zero_result_ = decltype(status.zero_result_)(v); \
|
||||
status.negative_flag_ = status.zero_result_ & decltype(status.negative_flag_)(m);
|
||||
#define set_neg_zero(v, m) \
|
||||
status.zero_result = decltype(status.zero_result)(v); \
|
||||
status.negative_flag = status.zero_result & decltype(status.negative_flag)(m);
|
||||
|
||||
#define set_neg_zero_overflow(v, m) \
|
||||
set_neg_zero(v, m); \
|
||||
status.overflow_flag_ = (decltype(status.zero_result_)(value) ^ status.zero_result_) & decltype(status.overflow_flag_)(m);
|
||||
status.overflow_flag = (decltype(status.zero_result)(value) ^ status.zero_result) & decltype(status.overflow_flag)(m);
|
||||
|
||||
#define decode_shift_count() \
|
||||
int shift_count = src.l & 63; \
|
||||
@ -867,15 +867,15 @@ template <
|
||||
const auto value = destination; \
|
||||
\
|
||||
if(!shift_count) { \
|
||||
status.carry_flag_ = status.overflow_flag_ = 0; \
|
||||
status.carry_flag = status.overflow_flag = 0; \
|
||||
} else { \
|
||||
destination = (shift_count < size) ? decltype(destination)(value << shift_count) : 0; \
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(value) & decltype(status.carry_flag_)( (1u << (size - 1)) >> (shift_count - 1) ); \
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(value) & decltype(status.carry_flag)( (1u << (size - 1)) >> (shift_count - 1) ); \
|
||||
\
|
||||
if(shift_count >= size) status.overflow_flag_ = value && (value != decltype(value)(-1)); \
|
||||
if(shift_count >= size) status.overflow_flag = value && (value != decltype(value)(-1)); \
|
||||
else { \
|
||||
const auto mask = decltype(destination)(0xffffffff << (size - shift_count)); \
|
||||
status.overflow_flag_ = mask & value && ((mask & value) != mask); \
|
||||
status.overflow_flag = mask & value && ((mask & value) != mask); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@ -885,7 +885,7 @@ template <
|
||||
case Operation::ASLm: {
|
||||
const auto value = src.w;
|
||||
src.w = uint16_t(value << 1);
|
||||
status.extend_flag_ = status.carry_flag_ = value & 0x8000;
|
||||
status.extend_flag = status.carry_flag = value & 0x8000;
|
||||
set_neg_zero_overflow(src.w, 0x8000);
|
||||
} break;
|
||||
case Operation::ASLb: asl(dest.b, 8); break;
|
||||
@ -897,7 +897,7 @@ template <
|
||||
const auto value = destination; \
|
||||
\
|
||||
if(!shift_count) { \
|
||||
status.carry_flag_ = 0; \
|
||||
status.carry_flag = 0; \
|
||||
} else { \
|
||||
destination = (shift_count < size) ? \
|
||||
decltype(destination)(\
|
||||
@ -907,7 +907,7 @@ template <
|
||||
decltype(destination)( \
|
||||
(value & decltype(value)(1 << (size - 1))) ? 0xffffffff : 0x000000000 \
|
||||
); \
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(value) & decltype(status.carry_flag_)(1 << (shift_count - 1)); \
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(value) & decltype(status.carry_flag)(1 << (shift_count - 1)); \
|
||||
} \
|
||||
\
|
||||
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||
@ -916,7 +916,7 @@ template <
|
||||
case Operation::ASRm: {
|
||||
const auto value = src.w;
|
||||
src.w = (value&0x8000) | (value >> 1);
|
||||
status.extend_flag_ = status.carry_flag_ = value & 1;
|
||||
status.extend_flag = status.carry_flag = value & 1;
|
||||
set_neg_zero_overflow(src.w, 0x8000);
|
||||
} break;
|
||||
case Operation::ASRb: asr(dest.b, 8); break;
|
||||
@ -927,24 +927,24 @@ template <
|
||||
#undef set_neg_zero_overflow
|
||||
#define set_neg_zero_overflow(v, m) \
|
||||
set_neg_zero(v, m); \
|
||||
status.overflow_flag_ = 0;
|
||||
status.overflow_flag = 0;
|
||||
|
||||
#undef set_flags
|
||||
#define set_flags(v, m, t) \
|
||||
status.zero_result_ = v; \
|
||||
status.negative_flag_ = status.zero_result_ & (m); \
|
||||
status.overflow_flag_ = 0; \
|
||||
status.carry_flag_ = value & (t);
|
||||
status.zero_result = v; \
|
||||
status.negative_flag = status.zero_result & (m); \
|
||||
status.overflow_flag = 0; \
|
||||
status.carry_flag = value & (t);
|
||||
|
||||
#define lsl(destination, size) {\
|
||||
decode_shift_count(); \
|
||||
const auto value = destination; \
|
||||
\
|
||||
if(!shift_count) { \
|
||||
status.carry_flag_ = 0; \
|
||||
status.carry_flag = 0; \
|
||||
} else { \
|
||||
destination = (shift_count < size) ? decltype(destination)(value << shift_count) : 0; \
|
||||
status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(value) & decltype(status.carry_flag_)( (1u << (size - 1)) >> (shift_count - 1) ); \
|
||||
status.extend_flag = status.carry_flag = decltype(status.carry_flag)(value) & decltype(status.carry_flag)( (1u << (size - 1)) >> (shift_count - 1) ); \
|
||||
} \
|
||||
\
|
||||
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||
@ -953,7 +953,7 @@ template <
|
||||
case Operation::LSLm: {
|
||||
const auto value = src.w;
|
||||
src.w = uint16_t(value << 1);
|
||||
status.extend_flag_ = status.carry_flag_ = value & 0x8000;
|
||||
status.extend_flag = status.carry_flag = value & 0x8000;
|
||||
set_neg_zero_overflow(src.w, 0x8000);
|
||||
} break;
|
||||
case Operation::LSLb: lsl(dest.b, 8); break;
|
||||
@ -965,10 +965,10 @@ template <
|
||||
const auto value = destination; \
|
||||
\
|
||||
if(!shift_count) { \
|
||||
status.carry_flag_ = 0; \
|
||||
status.carry_flag = 0; \
|
||||
} else { \
|
||||
destination = (shift_count < size) ? (value >> shift_count) : 0; \
|
||||
status.extend_flag_ = status.carry_flag_ = value & decltype(status.carry_flag_)(1 << (shift_count - 1)); \
|
||||
status.extend_flag = status.carry_flag = value & decltype(status.carry_flag)(1 << (shift_count - 1)); \
|
||||
} \
|
||||
\
|
||||
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||
@ -977,7 +977,7 @@ template <
|
||||
case Operation::LSRm: {
|
||||
const auto value = src.w;
|
||||
src.w = value >> 1;
|
||||
status.extend_flag_ = status.carry_flag_ = value & 1;
|
||||
status.extend_flag = status.carry_flag = value & 1;
|
||||
set_neg_zero_overflow(src.w, 0x8000);
|
||||
} break;
|
||||
case Operation::LSRb: lsr(dest.b, 8); break;
|
||||
@ -989,14 +989,14 @@ template <
|
||||
const auto value = destination; \
|
||||
\
|
||||
if(!shift_count) { \
|
||||
status.carry_flag_ = 0; \
|
||||
status.carry_flag = 0; \
|
||||
} else { \
|
||||
shift_count &= (size - 1); \
|
||||
destination = decltype(destination)( \
|
||||
(value << shift_count) | \
|
||||
(value >> (size - shift_count)) \
|
||||
); \
|
||||
status.carry_flag_ = decltype(status.carry_flag_)(destination & 1); \
|
||||
status.carry_flag = decltype(status.carry_flag)(destination & 1); \
|
||||
} \
|
||||
\
|
||||
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||
@ -1005,7 +1005,7 @@ template <
|
||||
case Operation::ROLm: {
|
||||
const auto value = src.w;
|
||||
src.w = uint16_t((value << 1) | (value >> 15));
|
||||
status.carry_flag_ = src.w & 1;
|
||||
status.carry_flag = src.w & 1;
|
||||
set_neg_zero_overflow(src.w, 0x8000);
|
||||
} break;
|
||||
case Operation::ROLb: rol(dest.b, 8); break;
|
||||
@ -1017,14 +1017,14 @@ template <
|
||||
const auto value = destination; \
|
||||
\
|
||||
if(!shift_count) { \
|
||||
status.carry_flag_ = 0; \
|
||||
status.carry_flag = 0; \
|
||||
} else { \
|
||||
shift_count &= (size - 1); \
|
||||
destination = decltype(destination)(\
|
||||
(value >> shift_count) | \
|
||||
(value << (size - shift_count)) \
|
||||
);\
|
||||
status.carry_flag_ = destination & decltype(status.carry_flag_)(1 << (size - 1)); \
|
||||
status.carry_flag = destination & decltype(status.carry_flag)(1 << (size - 1)); \
|
||||
} \
|
||||
\
|
||||
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||
@ -1033,7 +1033,7 @@ template <
|
||||
case Operation::RORm: {
|
||||
const auto value = src.w;
|
||||
src.w = uint16_t((value >> 1) | (value << 15));
|
||||
status.carry_flag_ = src.w & 0x8000;
|
||||
status.carry_flag = src.w & 0x8000;
|
||||
set_neg_zero_overflow(src.w, 0x8000);
|
||||
} break;
|
||||
case Operation::RORb: ror(dest.b, 8); break;
|
||||
@ -1044,11 +1044,11 @@ template <
|
||||
decode_shift_count(); \
|
||||
\
|
||||
shift_count %= (size + 1); \
|
||||
uint64_t compound = uint64_t(destination) | (status.extend_flag_ ? (1ull << size) : 0); \
|
||||
uint64_t compound = uint64_t(destination) | (status.extend_flag ? (1ull << size) : 0); \
|
||||
compound = \
|
||||
(compound << shift_count) | \
|
||||
(compound >> (size + 1 - shift_count)); \
|
||||
status.carry_flag_ = status.extend_flag_ = decltype(status.carry_flag_)((compound >> size) & 1); \
|
||||
status.carry_flag = status.extend_flag = decltype(status.carry_flag)((compound >> size) & 1); \
|
||||
destination = decltype(destination)(compound); \
|
||||
\
|
||||
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||
@ -1056,8 +1056,8 @@ template <
|
||||
|
||||
case Operation::ROXLm: {
|
||||
const auto value = src.w;
|
||||
src.w = uint16_t((value << 1) | (status.extend_flag_ ? 0x0001 : 0x0000));
|
||||
status.extend_flag_ = value & 0x8000;
|
||||
src.w = uint16_t((value << 1) | (status.extend_flag ? 0x0001 : 0x0000));
|
||||
status.extend_flag = value & 0x8000;
|
||||
set_flags_w(0x8000);
|
||||
} break;
|
||||
case Operation::ROXLb: roxl(dest.b, 8); break;
|
||||
@ -1068,11 +1068,11 @@ template <
|
||||
decode_shift_count(); \
|
||||
\
|
||||
shift_count %= (size + 1); \
|
||||
uint64_t compound = uint64_t(destination) | (status.extend_flag_ ? (1ull << size) : 0); \
|
||||
uint64_t compound = uint64_t(destination) | (status.extend_flag ? (1ull << size) : 0); \
|
||||
compound = \
|
||||
(compound >> shift_count) | \
|
||||
(compound << (size + 1 - shift_count)); \
|
||||
status.carry_flag_ = status.extend_flag_ = decltype(status.carry_flag_)((compound >> size) & 1); \
|
||||
status.carry_flag = status.extend_flag = decltype(status.carry_flag)((compound >> size) & 1); \
|
||||
destination = decltype(destination)(compound); \
|
||||
\
|
||||
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||
@ -1080,8 +1080,8 @@ template <
|
||||
|
||||
case Operation::ROXRm: {
|
||||
const auto value = src.w;
|
||||
src.w = (value >> 1) | (status.extend_flag_ ? 0x8000 : 0x0000);
|
||||
status.extend_flag_ = value & 0x0001;
|
||||
src.w = (value >> 1) | (status.extend_flag ? 0x8000 : 0x0000);
|
||||
status.extend_flag = value & 0x0001;
|
||||
set_flags_w(0x0001);
|
||||
} break;
|
||||
case Operation::ROXRb: roxr(dest.b, 8); break;
|
||||
@ -1147,21 +1147,21 @@ template <
|
||||
*/
|
||||
|
||||
case Operation::TSTb:
|
||||
status.carry_flag_ = status.overflow_flag_ = 0;
|
||||
status.zero_result_ = src.b;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80;
|
||||
status.carry_flag = status.overflow_flag = 0;
|
||||
status.zero_result = src.b;
|
||||
status.negative_flag = status.zero_result & 0x80;
|
||||
break;
|
||||
|
||||
case Operation::TSTw:
|
||||
status.carry_flag_ = status.overflow_flag_ = 0;
|
||||
status.zero_result_ = src.w;
|
||||
status.negative_flag_ = status.zero_result_ & 0x8000;
|
||||
status.carry_flag = status.overflow_flag = 0;
|
||||
status.zero_result = src.w;
|
||||
status.negative_flag = status.zero_result & 0x8000;
|
||||
break;
|
||||
|
||||
case Operation::TSTl:
|
||||
status.carry_flag_ = status.overflow_flag_ = 0;
|
||||
status.zero_result_ = src.l;
|
||||
status.negative_flag_ = status.zero_result_ & 0x80000000;
|
||||
status.carry_flag = status.overflow_flag = 0;
|
||||
status.zero_result = src.l;
|
||||
status.negative_flag = status.zero_result & 0x80000000;
|
||||
break;
|
||||
|
||||
case Operation::STOP:
|
||||
|
@ -15,61 +15,74 @@ namespace InstructionSet {
|
||||
namespace M68k {
|
||||
|
||||
struct Status {
|
||||
enum ConditionCode: uint16_t {
|
||||
Carry = (1 << 0),
|
||||
Overflow = (1 << 1),
|
||||
Zero = (1 << 2),
|
||||
Negative = (1 << 3),
|
||||
Extend = (1 << 4),
|
||||
|
||||
Supervisor = (1 << 13),
|
||||
Trace = (1 << 15),
|
||||
|
||||
InterruptPriorityMask = (0b111 << 8),
|
||||
};
|
||||
|
||||
/* b15 */
|
||||
uint_fast32_t trace_flag_ = 0; // The trace flag is set if this value is non-zero.
|
||||
uint_fast32_t trace_flag = 0; // The trace flag is set if this value is non-zero.
|
||||
|
||||
/* b13 */
|
||||
int is_supervisor_ = 0; // 1 => processor is in supervisor mode; 0 => it isn't.
|
||||
int is_supervisor = 0; // 1 => processor is in supervisor mode; 0 => it isn't.
|
||||
|
||||
/* b7–b9 */
|
||||
int interrupt_level_ = 0; // The direct integer value of the current interrupt level.
|
||||
int interrupt_level = 0; // The direct integer value of the current interrupt level.
|
||||
|
||||
/* b0–b4 */
|
||||
uint_fast32_t zero_result_ = 0; // The zero flag is set if this value is zero.
|
||||
uint_fast32_t carry_flag_ = 0; // The carry flag is set if this value is non-zero.
|
||||
uint_fast32_t extend_flag_ = 0; // The extend flag is set if this value is non-zero.
|
||||
uint_fast32_t overflow_flag_ = 0; // The overflow flag is set if this value is non-zero.
|
||||
uint_fast32_t negative_flag_ = 0; // The negative flag is set if this value is non-zero.
|
||||
uint_fast32_t zero_result = 0; // The zero flag is set if this value is zero.
|
||||
uint_fast32_t carry_flag = 0; // The carry flag is set if this value is non-zero.
|
||||
uint_fast32_t extend_flag = 0; // The extend flag is set if this value is non-zero.
|
||||
uint_fast32_t overflow_flag = 0; // The overflow flag is set if this value is non-zero.
|
||||
uint_fast32_t negative_flag = 0; // The negative flag is set if this value is non-zero.
|
||||
|
||||
/// Gets the current condition codes.
|
||||
constexpr uint16_t ccr() const {
|
||||
return
|
||||
(carry_flag_ ? 0x0001 : 0x0000) |
|
||||
(overflow_flag_ ? 0x0002 : 0x0000) |
|
||||
(zero_result_ ? 0x0000 : 0x0004) |
|
||||
(negative_flag_ ? 0x0008 : 0x0000) |
|
||||
(extend_flag_ ? 0x0010 : 0x0000);
|
||||
(carry_flag ? ConditionCode::Carry : 0) |
|
||||
(overflow_flag ? ConditionCode::Overflow : 0) |
|
||||
(zero_result ? 0 : ConditionCode::Zero) |
|
||||
(negative_flag ? ConditionCode::Negative : 0) |
|
||||
(extend_flag ? ConditionCode::Extend : 0);
|
||||
}
|
||||
|
||||
/// Sets the current condition codes.
|
||||
constexpr void set_ccr(uint16_t ccr) {
|
||||
carry_flag = ccr & ConditionCode::Carry;
|
||||
overflow_flag = ccr & ConditionCode::Overflow;
|
||||
zero_result = ~ccr & ConditionCode::Zero;
|
||||
negative_flag = ccr & ConditionCode::Negative;
|
||||
extend_flag = ccr & ConditionCode::Extend;
|
||||
}
|
||||
|
||||
/// Gets the current value of the status register.
|
||||
constexpr uint16_t status() const {
|
||||
return uint16_t(
|
||||
ccr() |
|
||||
(interrupt_level_ << 8) |
|
||||
(trace_flag_ ? 0x8000 : 0x0000) |
|
||||
(is_supervisor_ << 13)
|
||||
(interrupt_level << 8) |
|
||||
(trace_flag ? ConditionCode::Trace : 0) |
|
||||
(is_supervisor << 13)
|
||||
);
|
||||
}
|
||||
|
||||
/// Sets the current condition codes.
|
||||
constexpr void set_ccr(uint16_t ccr) {
|
||||
carry_flag_ = (ccr) & 0x0001;
|
||||
overflow_flag_ = (ccr) & 0x0002;
|
||||
zero_result_ = ((ccr) & 0x0004) ^ 0x0004;
|
||||
negative_flag_ = (ccr) & 0x0008;
|
||||
extend_flag_ = (ccr) & 0x0010;
|
||||
}
|
||||
|
||||
/// Sets the current value of the status register;
|
||||
/// @returns @c true if the processor finishes in supervisor mode; @c false otherwise.
|
||||
constexpr bool set_status(uint16_t status) {
|
||||
set_ccr(status);
|
||||
|
||||
interrupt_level_ = (status >> 8) & 7;
|
||||
trace_flag_ = status & 0x8000;
|
||||
is_supervisor_ = (status >> 13) & 1;
|
||||
interrupt_level = (status >> 8) & 7;
|
||||
trace_flag = status & ConditionCode::Trace;
|
||||
is_supervisor = (status >> 13) & 1;
|
||||
|
||||
return is_supervisor_;
|
||||
return is_supervisor;
|
||||
}
|
||||
|
||||
/// Evaluates @c condition.
|
||||
@ -78,24 +91,24 @@ struct Status {
|
||||
default:
|
||||
case Condition::True: return true;
|
||||
case Condition::False: return false;
|
||||
case Condition::High: return zero_result_ && !carry_flag_;
|
||||
case Condition::LowOrSame: return !zero_result_ || carry_flag_;
|
||||
case Condition::CarryClear: return !carry_flag_;
|
||||
case Condition::CarrySet: return carry_flag_;
|
||||
case Condition::NotEqual: return zero_result_;
|
||||
case Condition::Equal: return !zero_result_;
|
||||
case Condition::OverflowClear: return !overflow_flag_;
|
||||
case Condition::OverflowSet: return overflow_flag_;
|
||||
case Condition::Positive: return !negative_flag_;
|
||||
case Condition::Negative: return negative_flag_;
|
||||
case Condition::High: return zero_result && !carry_flag;
|
||||
case Condition::LowOrSame: return !zero_result || carry_flag;
|
||||
case Condition::CarryClear: return !carry_flag;
|
||||
case Condition::CarrySet: return carry_flag;
|
||||
case Condition::NotEqual: return zero_result;
|
||||
case Condition::Equal: return !zero_result;
|
||||
case Condition::OverflowClear: return !overflow_flag;
|
||||
case Condition::OverflowSet: return overflow_flag;
|
||||
case Condition::Positive: return !negative_flag;
|
||||
case Condition::Negative: return negative_flag;
|
||||
case Condition::GreaterThanOrEqual:
|
||||
return (negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_);
|
||||
return (negative_flag && overflow_flag) || (!negative_flag && !overflow_flag);
|
||||
case Condition::LessThan:
|
||||
return (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_);
|
||||
return (negative_flag && !overflow_flag) || (!negative_flag && overflow_flag);
|
||||
case Condition::GreaterThan:
|
||||
return zero_result_ && ((negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_));
|
||||
return zero_result && ((negative_flag && overflow_flag) || (!negative_flag && !overflow_flag));
|
||||
case Condition::LessThanOrEqual:
|
||||
return !zero_result_ || (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_);
|
||||
return !zero_result || (negative_flag && !overflow_flag) || (!negative_flag && overflow_flag);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -21,10 +21,10 @@ using namespace InstructionSet::M68k;
|
||||
|
||||
- (Status)statusWithflamewingFlags:(int)flags {
|
||||
Status status;
|
||||
status.carry_flag_ = status.extend_flag_ = flags & 2;
|
||||
status.zero_result_ = ~flags & 1;
|
||||
status.negative_flag_ = 0;
|
||||
status.overflow_flag_ = 0;
|
||||
status.carry_flag = status.extend_flag = flags & 2;
|
||||
status.zero_result = ~flags & 1;
|
||||
status.negative_flag = 0;
|
||||
status.overflow_flag = 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -86,6 +86,8 @@ using namespace InstructionSet::M68k;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
// Test NBCD.
|
||||
for(int source = 0; source < 256; source++) {
|
||||
for(int flags = 0; flags < 4; flags++) {
|
||||
@ -97,7 +99,7 @@ using namespace InstructionSet::M68k;
|
||||
perform<Model::M68000, NullFlowController, Operation::SBCD>(
|
||||
Preinstruction(), s, d, status, flow_controller);
|
||||
|
||||
[self validate:bytes source:source dest:0 flags:flags result:d.l status:status operation:@"NBCD"];
|
||||
[self validate:bytes source:source dest:0 flags:flags result:s.l status:status operation:@"NBCD"];
|
||||
bytes += 2;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user