1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Implements CLR, NEG, NEGX and NOT.

This commit is contained in:
Thomas Harte 2019-04-07 22:07:39 -04:00
parent 06a2f59bd0
commit 652f4ebfed
3 changed files with 240 additions and 7 deletions

View File

@ -58,6 +58,9 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
active_micro_op_ = active_program_->micro_operations;
}
#define sub_overflow() (source ^ destination) & (destination ^ result)
#define add_overflow() ~(source ^ destination) & (destination ^ result)
switch(active_micro_op_->action) {
default:
std::cerr << "Unhandled 68000 micro op action " << std::hex << active_micro_op_->action << std::endl;
@ -86,7 +89,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
zero_result_ |= result & 0xff;
extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = ~(source ^ destination) & (destination ^ result) & 0x80;
overflow_flag_ = add_overflow() & 0x80;
// Store the result.
active_program_->destination->halves.low.halves.low = uint8_t(result);
@ -101,7 +104,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
zero_result_ = active_program_->destination->halves.low.halves.low = uint8_t(result);
extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = ~(source ^ destination) & (destination ^ result) & 0x80;
overflow_flag_ = add_overflow() & 0x80;
} break;
case Operation::ADDw: {
@ -112,7 +115,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
zero_result_ = active_program_->destination->halves.low.full = uint16_t(result);
extend_flag_ = carry_flag_ = result & ~0xffff;
negative_flag_ = result & 0x8000;
overflow_flag_ = ~(source ^ destination) & (destination ^ result) & 0x8000;
overflow_flag_ = add_overflow() & 0x8000;
} break;
case Operation::ADDl: {
@ -123,7 +126,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
zero_result_ = active_program_->destination->halves.low.full = uint32_t(result);
extend_flag_ = carry_flag_ = result >> 32;
negative_flag_ = result & 0x80000000;
overflow_flag_ = ~(source ^ destination) & (destination ^ result) & 0x80000000;
overflow_flag_ = add_overflow() & 0x80000000;
} break;
case Operation::ADDAw:
@ -210,6 +213,25 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
}
} break;
/*
CLRs: store 0 to the destination, set the zero flag, and clear
negative, overflow and carry.
*/
case Operation::CLRb:
active_program_->destination->halves.low.halves.low = 0;
negative_flag_ = overflow_flag_ = carry_flag_ = zero_result_ = 0;
break;
case Operation::CLRw:
active_program_->destination->halves.low.full = 0;
negative_flag_ = overflow_flag_ = carry_flag_ = zero_result_ = 0;
break;
case Operation::CLRl:
active_program_->destination->full = 0;
negative_flag_ = overflow_flag_ = carry_flag_ = zero_result_ = 0;
break;
/*
CMP.b, CMP.l and CMP.w: sets the condition flags (other than extend) based on a subtraction
of the source from the destination; the result of the subtraction is not stored.
@ -222,7 +244,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
zero_result_ = result & 0xff;
carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x80;
overflow_flag_ = sub_overflow() & 0x80;
} break;
case Operation::CMPw: {
@ -233,7 +255,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
zero_result_ = result & 0xffff;
carry_flag_ = result & ~0xffff;
negative_flag_ = result & 0x8000;
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x8000;
overflow_flag_ = sub_overflow() & 0x8000;
} break;
case Operation::CMPl: {
@ -244,7 +266,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
zero_result_ = uint32_t(result);
carry_flag_ = result >> 32;
negative_flag_ = result & 0x80000000;
overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x80000000;
overflow_flag_ = sub_overflow() & 0x80000000;
} break;
// JMP: copies the source to the program counter.
@ -310,12 +332,111 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
active_program_->source->halves.low.full = get_status();
break;
/*
NEGs: negatives the destination, setting the zero,
negative, overflow and carry flags appropriate, and extend.
*/
case Operation::NEGb: {
const int source = 0;
const int destination = active_program_->destination->halves.low.halves.low;
const int result = source - destination;
active_program_->destination->halves.low.halves.low = result;
zero_result_ = result & 0xff;
extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = sub_overflow() & 0x80;
} break;
case Operation::NEGw: {
const int source = 0;
const int destination = active_program_->destination->halves.low.full;
const int result = source - destination;
active_program_->destination->halves.low.full = result;
zero_result_ = result & 0xffff;
extend_flag_ = carry_flag_ = result & ~0xffff;
negative_flag_ = result & 0x8000;
overflow_flag_ = sub_overflow() & 0x8000;
} break;
case Operation::NEGl: {
const int source = 0;
const int destination = active_program_->destination->full;
int64_t result = source - destination;
active_program_->destination->full = uint32_t(result);
zero_result_ = uint_fast32_t(result);
extend_flag_ = carry_flag_ = result >> 32;
negative_flag_ = result & 0x80000000;
overflow_flag_ = sub_overflow() & 0x80000000;
} break;
/*
NEGXs: NEG, with extend.
*/
case Operation::NEGXb: {
const int source = 0;
const int destination = active_program_->destination->halves.low.halves.low;
const int result = source - destination - (extend_flag_ ? 1 : 0);
active_program_->destination->halves.low.halves.low = result;
zero_result_ = result & 0xff;
extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = sub_overflow() & 0x80;
} break;
case Operation::NEGXw: {
const int source = 0;
const int destination = active_program_->destination->halves.low.full;
const int result = source - destination - (extend_flag_ ? 1 : 0);
active_program_->destination->halves.low.full = result;
zero_result_ = result & 0xffff;
extend_flag_ = carry_flag_ = result & ~0xffff;
negative_flag_ = result & 0x8000;
overflow_flag_ = sub_overflow() & 0x8000;
} break;
case Operation::NEGXl: {
const int source = 0;
const int destination = active_program_->destination->full;
int64_t result = source - destination - (extend_flag_ ? 1 : 0);
active_program_->destination->full = result;
zero_result_ = result;
extend_flag_ = carry_flag_ = result >> 32;
negative_flag_ = result & 0x80000000;
overflow_flag_ = sub_overflow() & 0x80000000;
} break;
/*
The no-op.
*/
case Operation::None:
break;
// NOTs: take the logical inverse, affecting the negative and zero flags.
case Operation::NOTb:
active_program_->destination->halves.low.halves.low ^= 0xff;
zero_result_ = active_program_->destination->halves.low.halves.low;
negative_flag_ = zero_result_ & 0x80;
break;
case Operation::NOTw:
active_program_->destination->halves.low.full ^= 0xffff;
zero_result_ = active_program_->destination->halves.low.full;
negative_flag_ = zero_result_ & 0x8000;
break;
case Operation::NOTl:
active_program_->destination->full ^= 0xffffffff;
zero_result_ = active_program_->destination->full;
negative_flag_ = zero_result_ & 0x80000000;
break;
/*
SBCD subtracts the lowest byte of the source from that of the destination using
BCD arithmetic, obeying the extend flag.

View File

@ -270,6 +270,7 @@ struct ProcessorStorageConstructor {
BTSTIMM, // six lowest bits are [mode, register], decoding to BTST #
CMP,
DBcc, // the low three bits nominate a register; everything else is decoded in real time
CLRNEGNEGXNOT,
};
using Operation = ProcessorStorage::Operation;
@ -343,6 +344,19 @@ struct ProcessorStorageConstructor {
{0xffc0, 0x0800, Operation::BTSTb, Decoder::BTSTIMM}, // 4-63 (p167)
{0xf0f8, 0x50c8, Operation::DBcc, Decoder::DBcc}, // 4-91 (p195)
{0xffc0, 0x4200, Operation::CLRb, Decoder::CLRNEGNEGXNOT}, // 4-73 (p177)
{0xffc0, 0x4240, Operation::CLRw, Decoder::CLRNEGNEGXNOT}, // 4-73 (p177)
{0xffc0, 0x4280, Operation::CLRl, Decoder::CLRNEGNEGXNOT}, // 4-73 (p177)
{0xffc0, 0x4400, Operation::NEGb, Decoder::CLRNEGNEGXNOT}, // 4-144 (p248)
{0xffc0, 0x4440, Operation::NEGw, Decoder::CLRNEGNEGXNOT}, // 4-144 (p248)
{0xffc0, 0x4480, Operation::NEGl, Decoder::CLRNEGNEGXNOT}, // 4-144 (p248)
{0xffc0, 0x4000, Operation::NEGXb, Decoder::CLRNEGNEGXNOT}, // 4-146 (p250)
{0xffc0, 0x4040, Operation::NEGXw, Decoder::CLRNEGNEGXNOT}, // 4-146 (p250)
{0xffc0, 0x4080, Operation::NEGXl, Decoder::CLRNEGNEGXNOT}, // 4-146 (p250)
{0xffc0, 0x4600, Operation::NOTb, Decoder::CLRNEGNEGXNOT}, // 4-148 (p250)
{0xffc0, 0x4640, Operation::NOTw, Decoder::CLRNEGNEGXNOT}, // 4-148 (p250)
{0xffc0, 0x4680, Operation::NOTl, Decoder::CLRNEGNEGXNOT}, // 4-148 (p250)
};
std::vector<size_t> micro_op_pointers(65536, std::numeric_limits<size_t>::max());
@ -827,6 +841,99 @@ struct ProcessorStorageConstructor {
}
} break;
case Decoder::CLRNEGNEGXNOT: {
const bool is_byte_access = !!((instruction >> 6)&3);
const bool is_long_word_access = ((instruction >> 6)&3) == 2;
storage_.instructions[instruction].set_destination(storage_, ea_mode, ea_register);
const int mode = combined_mode(ea_mode, ea_register);
switch((is_long_word_access ? 0x100 : 0x000) | mode) {
default: continue;
case 0x000: // [CLR/NEG/NEGX/NOT].bw Dn
case 0x100: // [CLR/NEG/NEGX/NOT].l Dn
op(Action::PerformOperation, seq("np"));
break;
case 0x002: // [CLR/NEG/NEGX/NOT].bw (An)
case 0x003: // [CLR/NEG/NEGX/NOT].bw (An)+
op(Action::None, seq("nrd", { a(ea_register) }, !is_byte_access));
op(Action::PerformOperation, seq("np nw", { a(ea_register) }, !is_byte_access));
if(ea_mode == 0x03) {
op(int(is_byte_access ? Action::Increment1 : Action::Increment2) | MicroOp::DestinationMask);
}
break;
case 0x102: // [CLR/NEG/NEGX/NOT].l (An)
case 0x103: // [CLR/NEG/NEGX/NOT].l (An)+
op(int(Action::CopyToEffectiveAddress) | MicroOp::DestinationMask, seq("nRd+ nrd", { ea(1), ea(1) }));
op(Action::PerformOperation, seq("np nw- nW", { ea(1), ea(1) }));
if(ea_mode == 0x03) {
op(int(Action::Increment4) | MicroOp::DestinationMask);
}
break;
case 0x004: // [CLR/NEG/NEGX/NOT].bw -(An)
op( int(is_byte_access ? Action::Decrement1 : Action::Decrement2) | MicroOp::DestinationMask,
seq("nrd", { a(ea_register) }, !is_byte_access));
op(Action::PerformOperation, seq("np nw", { a(ea_register) }, !is_byte_access));
break;
case 0x104: // [CLR/NEG/NEGX/NOT].l -(An)
op(int(Action::Decrement4) | MicroOp::DestinationMask);
op(int(Action::CopyToEffectiveAddress) | MicroOp::DestinationMask,
seq("n nRd+ nrd", { ea(1), ea(1) }));
op(Action::PerformOperation, seq("np nw- nW", { ea(1), ea(1) }));
break;
case 0x005: // [CLR/NEG/NEGX/NOT].bw (d16, An)
case 0x006: // [CLR/NEG/NEGX/NOT].bw (d8, An, Xn)
op( calc_action_for_mode(ea_mode) | MicroOp::DestinationMask,
seq(pseq("np nrd", ea_mode), { ea(1) },
!is_byte_access));
op(Action::PerformOperation, seq("np nw", { ea(1) }, !is_byte_access));
break;
case 0x105: // [CLR/NEG/NEGX/NOT].l (d16, An)
case 0x106: // [CLR/NEG/NEGX/NOT].l (d8, An, Xn)
op( calc_action_for_mode(ea_mode) | MicroOp::DestinationMask,
seq(pseq("np nRd+ nrd", ea_mode), { ea(1), ea(1) }));
op(Action::PerformOperation, seq("np nw- nW", { ea(1), ea(1) }));
break;
case 0x010: // [CLR/NEG/NEGX/NOT].bw (xxx).w
op( int(Action::AssembleWordAddressFromPrefetch) | MicroOp::DestinationMask,
seq("np nrd", { ea(1) }, !is_byte_access));
op(Action::PerformOperation,
seq("np nw", { ea(1) }, !is_byte_access));
break;
case 0x110: // [CLR/NEG/NEGX/NOT].l (xxx).w
op( int(Action::AssembleWordAddressFromPrefetch) | MicroOp::DestinationMask,
seq("np nRd+ nrd", { ea(1), ea(1) }));
op(Action::PerformOperation,
seq("np nw- nW", { ea(1), ea(1) }));
break;
case 0x011: // [CLR/NEG/NEGX/NOT].bw (xxx).l
op(Action::None, seq("np"));
op( int(Action::AssembleLongWordAddressFromPrefetch) | MicroOp::DestinationMask,
seq("np nrd", { ea(1) }, !is_byte_access));
op(Action::PerformOperation,
seq("np nw", { ea(1) }, !is_byte_access));
break;
case 0x111: // [CLR/NEG/NEGX/NOT].l (xxx).l
op(Action::None, seq("np"));
op( int(Action::AssembleLongWordAddressFromPrefetch) | MicroOp::DestinationMask,
seq("np nRd+ nrd", { ea(1), ea(1) }));
op(Action::PerformOperation,
seq("np nw- nW", { ea(1), ea(1) }));
break;
}
} break;
case Decoder::CMP: {
const auto source_register = (instruction >> 9) & 7;

View File

@ -62,6 +62,11 @@ class ProcessorStorage {
JMP,
BRA, Bcc,
DBcc,
CLRb, CLRw, CLRl,
NEGXb, NEGXw, NEGXl,
NEGb, NEGw, NEGl,
NOTb, NOTw, NOTl,
};
/*!