mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-27 15:50:56 +00:00
1503 lines
41 KiB
Plaintext
1503 lines
41 KiB
Plaintext
//
|
|
// 68000Bitwise.m
|
|
// Clock SignalTests
|
|
//
|
|
// Created by Thomas Harte on 28/06/2019.
|
|
//
|
|
// Largely ported from the tests of the Portable 68k Emulator.
|
|
//
|
|
|
|
#import <XCTest/XCTest.h>
|
|
|
|
#include "TestRunner68000.hpp"
|
|
|
|
@interface M68000BitwiseTests : XCTestCase
|
|
@end
|
|
|
|
@implementation M68000BitwiseTests {
|
|
std::unique_ptr<RAM68000> _machine;
|
|
}
|
|
|
|
- (void)setUp {
|
|
_machine = std::make_unique<RAM68000>();
|
|
}
|
|
|
|
- (void)tearDown {
|
|
_machine.reset();
|
|
}
|
|
|
|
// MARK: AND
|
|
|
|
- (void)testANDb_Dn {
|
|
_machine->set_program({
|
|
0xc604 // AND.b D4, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54ff7856;
|
|
state.data[4] = 0x9853abcd;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54ff7844);
|
|
XCTAssertEqual(state.data[4], 0x9853abcd);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 4);
|
|
}
|
|
|
|
- (void)testANDw_Dn {
|
|
_machine->set_program({
|
|
0xc644 // AND.w D4, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.data[4] = 0x9853fbcd;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff844);
|
|
XCTAssertEqual(state.data[4], 0x9853fbcd);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 4);
|
|
}
|
|
|
|
- (void)testANDl_Dn {
|
|
_machine->set_program({
|
|
0xc684 // AND.l D4, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.data[4] = 0x9853fbcd;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x1053f844);
|
|
XCTAssertEqual(state.data[4], 0x9853fbcd);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)performANDx_Ind:(uint16_t)opcode {
|
|
_machine->set_program({
|
|
opcode
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x3000) = 0x0053;
|
|
*_machine->ram_at(0x3002) = 0xfb00;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x0053);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb00);
|
|
XCTAssertEqual(state.address[4], 0x3000);
|
|
}
|
|
|
|
- (void)testANDb_Ind {
|
|
[self performANDx_Ind:0xc614]; // AND.b (A4), D3
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff800);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)testANDw_Ind {
|
|
[self performANDx_Ind:0xc654]; // AND.w (A4), D3
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54ff0052);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)testANDl_Ind {
|
|
[self performANDx_Ind:0xc694]; // AND.l (A4), D3
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x0053f800);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 14);
|
|
}
|
|
|
|
- (void)performANDx_PostInc:(uint16_t)opcode {
|
|
_machine->set_program({
|
|
opcode // AND.B (A4)+, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x3000) = 0x0053;
|
|
*_machine->ram_at(0x3002) = 0xfb00;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
}
|
|
|
|
- (void)testANDb_PostInc_A4 {
|
|
[self performANDx_PostInc:0xc61c]; // AND.B (A4)+, D3
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff800);
|
|
XCTAssertEqual(state.address[4], 0x3001);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)testANDb_PostInc_A7 {
|
|
_machine->set_program({
|
|
0xc61f // AND.B (A7)+, D3
|
|
});
|
|
_machine->set_initial_stack_pointer(0x3000);
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
*_machine->ram_at(0x3000) = 0x0053;
|
|
*_machine->ram_at(0x3002) = 0xfb00;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff800);
|
|
XCTAssertEqual(state.stack_pointer(), 0x3002);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)testANDw_PostInc_A4 {
|
|
[self performANDx_PostInc:0xc65c]; // AND.w (A4)+, D3
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54ff0052);
|
|
XCTAssertEqual(state.address[4], 0x3002);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)testANDl_PostInc_A4 {
|
|
[self performANDx_PostInc:0xc69c]; // AND.l (A4)+, D3
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x0053f800);
|
|
XCTAssertEqual(state.address[4], 0x3004);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 14);
|
|
}
|
|
|
|
// Omitted: address error test.
|
|
|
|
- (void)testANDl_PreDec {
|
|
_machine->set_program({
|
|
0xc6a4 // AND.l -(A4), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3004;
|
|
*_machine->ram_at(0x3000) = 0x0053;
|
|
*_machine->ram_at(0x3002) = 0xfb00;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x0053);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb00);
|
|
XCTAssertEqual(state.address[4], 0x3000);
|
|
XCTAssertEqual(state.data[3], 0x0053f800);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(16, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_d16An {
|
|
_machine->set_program({
|
|
0xc6ac, 0xfffa // AND.l -6(A4), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3006;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1253);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb34);
|
|
XCTAssertEqual(state.address[4], 0x3006);
|
|
XCTAssertEqual(state.data[3], 0x1053f814);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(18, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_d8AnDnw_positive {
|
|
_machine->set_program({
|
|
0xc6b4, 0x6006 // AND.l 6(A4, D6.W), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.data[6] = 0xfffffffd;
|
|
state.address[4] = 0x2ffd;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1253);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb34);
|
|
XCTAssertEqual(state.address[4], 0x2ffd);
|
|
XCTAssertEqual(state.data[3], 0x1053f814);
|
|
XCTAssertEqual(state.data[6], 0xfffffffd);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_d8AnDnw_negative {
|
|
_machine->set_program({
|
|
0xc6b4, 0x60fe // AND.l -2(A4, D6.W), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.data[6] = 0xf001fffd;
|
|
state.address[4] = 0x3005;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1253);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb34);
|
|
XCTAssertEqual(state.address[4], 0x3005);
|
|
XCTAssertEqual(state.data[3], 0x1053f814);
|
|
XCTAssertEqual(state.data[6], 0xf001fffd);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_d8AnDnl {
|
|
_machine->set_program({
|
|
0xc6b4, 0x6801 // AND.l 6(A4, D6.W), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.data[6] = 0xffffffff;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1253);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb34);
|
|
XCTAssertEqual(state.address[4], 0x3000);
|
|
XCTAssertEqual(state.data[3], 0x1053f814);
|
|
XCTAssertEqual(state.data[6], 0xffffffff);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_XXXw {
|
|
_machine->set_program({
|
|
0xc6b8, 0x3000 // AND.l $3000.w, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1253);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb34);
|
|
XCTAssertEqual(state.data[3], 0x1053f814);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(18, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_XXXl {
|
|
_machine->set_program({
|
|
0xc6b9, 0x0001, 0x1170 // AND.L $11170.l, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
*_machine->ram_at(0x11170) = 0x1253;
|
|
*_machine->ram_at(0x11172) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x11170), 0x1253);
|
|
XCTAssertEqual(*_machine->ram_at(0x11172), 0xfb34);
|
|
XCTAssertEqual(state.data[3], 0x1053f814);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(22, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_d16PC {
|
|
_machine->set_program({
|
|
0xc6ba, 0xfffa // AND.l -6(PC), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
*_machine->ram_at(0xffc) = 0x383c;
|
|
*_machine->ram_at(0xffe) = 0x1234;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0xffc), 0x383c);
|
|
XCTAssertEqual(*_machine->ram_at(0xffe), 0x1234);
|
|
XCTAssertEqual(state.data[3], 0x103c1014);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(18, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_d8AnPC {
|
|
_machine->set_program({
|
|
0xc6bb, 0x10f6 // and.l -10(PC), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.data[1] = 4;
|
|
*_machine->ram_at(0xffc) = 0x383c;
|
|
*_machine->ram_at(0xffe) = 0x1234;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0xffc), 0x383c);
|
|
XCTAssertEqual(*_machine->ram_at(0xffe), 0x1234);
|
|
XCTAssertEqual(state.data[3], 0x103c1014);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDb_Imm {
|
|
_machine->set_program({
|
|
0xc63c, 0x0034 // AND.b #$34, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff814);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(8, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDw_Imm {
|
|
_machine->set_program({
|
|
0xc67c, 0x1234 // AND.w #$1234, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54ff1014);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(8, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_Imm {
|
|
_machine->set_program({
|
|
0xc6bc, 0x3456, 0x1234 // AND.l #$34561234, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x14561014);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(16, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_IndTarget {
|
|
_machine->set_program({
|
|
0xc794 // AND.l D3, (A4)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb03;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff856);
|
|
XCTAssertEqual(state.address[4], 0x3000);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1053);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xf802);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_PostIncTarget {
|
|
_machine->set_program({
|
|
0xc79c // AND.l D3, (A4)+
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb03;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff856);
|
|
XCTAssertEqual(state.address[4], 0x3004);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1053);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xf802);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_PreDecTarget {
|
|
_machine->set_program({
|
|
0xc7a4 // AND.l D3, -(A4)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x2ffc) = 0x1253;
|
|
*_machine->ram_at(0x2ffe) = 0xfb03;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff856);
|
|
XCTAssertEqual(state.address[4], 0x2ffc);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(*_machine->ram_at(0x2ffc), 0x1053);
|
|
XCTAssertEqual(*_machine->ram_at(0x2ffe), 0xf802);
|
|
XCTAssertEqual(22, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_d16AnTarget {
|
|
_machine->set_program({
|
|
0xc7ac, 0x0002 // AND.l D3, 2(A4)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x3002) = 0x1253;
|
|
*_machine->ram_at(0x3004) = 0xfb03;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff856);
|
|
XCTAssertEqual(state.address[4], 0x3000);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0x1053);
|
|
XCTAssertEqual(*_machine->ram_at(0x3004), 0xf802);
|
|
XCTAssertEqual(24, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDl_xxxWTarget {
|
|
_machine->set_program({
|
|
0xc7b8, 0x3000 // AND.l D3, ($3000).w
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3000;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb03;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff856);
|
|
XCTAssertEqual(state.address[4], 0x3000);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1053);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xf802);
|
|
XCTAssertEqual(24, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: BCHG
|
|
|
|
- (void)performBCHGD0D1:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x0340 // BCHG D1, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
state.data[1] = d1;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], d1);
|
|
}
|
|
|
|
- (void)testBCHG_D0D1_0 {
|
|
[self performBCHGD0D1:0];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345679);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 6);
|
|
}
|
|
|
|
- (void)testBCHG_D0D1_10 {
|
|
[self performBCHGD0D1:10];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345278);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 6);
|
|
}
|
|
|
|
- (void)testBCHG_D0D1_48 {
|
|
[self performBCHGD0D1:48];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12355678);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)performBCHGD1Ind:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x0350 // BCHG D1, (A0)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.address[0] = 0x3000;
|
|
state.data[1] = d1;
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], d1);
|
|
XCTAssertEqual(state.address[0], 0x3000);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 12);
|
|
}
|
|
|
|
- (void)testBCHG_D1Ind_48 {
|
|
[self performBCHGD1Ind:48];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7900);
|
|
}
|
|
|
|
- (void)testBCHG_D1Ind_7 {
|
|
[self performBCHGD1Ind:7];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0xf800);
|
|
}
|
|
|
|
- (void)performBCHGImm:(uint16_t)immediate {
|
|
_machine->set_program({
|
|
0x0840, immediate // BCHG #, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
}
|
|
|
|
- (void)testBCHG_Imm_31 {
|
|
[self performBCHGImm:31];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x92345678);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 12);
|
|
}
|
|
|
|
- (void)testBCHG_Imm_4 {
|
|
[self performBCHGImm:4];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345668);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 10);
|
|
}
|
|
|
|
- (void)testBCHG_ImmWWWx {
|
|
_machine->set_program({
|
|
0x0878, 0x0006, 0x3000 // BCHG #6, ($3000).W
|
|
});
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 20);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x3800);
|
|
}
|
|
|
|
// MARK: BCLR
|
|
|
|
- (void)performBCLRD0D1:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x0380 // BCLR D1, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
state.data[1] = d1;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], d1);
|
|
}
|
|
|
|
- (void)testBCLR_D0D1_0 {
|
|
[self performBCLRD0D1:0];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345678);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)testBCLR_D0D1_10 {
|
|
[self performBCLRD0D1:10];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345278);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)testBCLR_D0D1_50 {
|
|
[self performBCLRD0D1:50];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12305678);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 10);
|
|
}
|
|
|
|
- (void)performBCLRD1Ind:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x0390 // BCLR D1, (A0)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.address[0] = 0x3000;
|
|
state.data[1] = d1;
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], d1);
|
|
XCTAssertEqual(state.address[0], 0x3000);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 12);
|
|
}
|
|
|
|
- (void)testBCLR_D1Ind_50 {
|
|
[self performBCLRD1Ind:50];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7800);
|
|
}
|
|
|
|
- (void)testBCLR_D1Ind_3 {
|
|
[self performBCLRD1Ind:3];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7000);
|
|
}
|
|
|
|
- (void)performBCLRImm:(uint16_t)immediate {
|
|
_machine->set_program({
|
|
0x0880, immediate // BCLR #, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
}
|
|
|
|
- (void)testBCLR_Imm_28 {
|
|
[self performBCLRImm:28];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x02345678);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 14);
|
|
}
|
|
|
|
- (void)testBCLR_Imm_4 {
|
|
[self performBCLRImm:4];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345668);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 12);
|
|
}
|
|
|
|
- (void)testBCLR_ImmWWWx {
|
|
_machine->set_program({
|
|
0x08b8, 0x0006, 0x3000 // BCLR #6, ($3000).W
|
|
});
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 20);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x3800);
|
|
}
|
|
|
|
// MARK: BSET
|
|
|
|
- (void)performBSETD0D1:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x03c0 // BSET D1, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
state.data[1] = d1;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], d1);
|
|
}
|
|
|
|
- (void)testBSET_D0D1_0 {
|
|
[self performBSETD0D1:0];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345679);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 6);
|
|
}
|
|
|
|
- (void)testBSET_D0D1_10 {
|
|
[self performBSETD0D1:10];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345678);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 6);
|
|
}
|
|
|
|
- (void)testBSET_D0D1_49 {
|
|
[self performBSETD0D1:49];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12365678);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 8);
|
|
}
|
|
|
|
- (void)performBSETD1Ind:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x03d0 // BSET D1, (A0)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.address[0] = 0x3000;
|
|
state.data[1] = d1;
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], d1);
|
|
XCTAssertEqual(state.address[0], 0x3000);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 12);
|
|
}
|
|
|
|
- (void)testBSET_D1Ind_50 {
|
|
[self performBSETD1Ind:50];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7c00);
|
|
}
|
|
|
|
- (void)testBSET_D1Ind_3 {
|
|
[self performBSETD1Ind:3];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7800);
|
|
}
|
|
|
|
- (void)performBSETImm:(uint16_t)immediate {
|
|
_machine->set_program({
|
|
0x08c0, immediate // BSET #, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
}
|
|
|
|
- (void)testBSET_Imm_28 {
|
|
[self performBSETImm:28];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345678);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 12);
|
|
}
|
|
|
|
- (void)testBSET_Imm_2 {
|
|
[self performBSETImm:2];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x1234567c);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 10);
|
|
}
|
|
|
|
- (void)testBSET_ImmWWWx {
|
|
_machine->set_program({
|
|
0x08f8, 0x0006, 0x3000 // BSET #6, ($3000).W
|
|
});
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 20);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7800);
|
|
}
|
|
|
|
// MARK: BTST
|
|
|
|
- (void)performBTSTD0D1:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x0300 // BTST D1, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
state.data[1] = d1;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345678);
|
|
XCTAssertEqual(state.data[1], d1);
|
|
XCTAssertEqual(6, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testBTST_D0D1_0 {
|
|
[self performBTSTD0D1:0];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
}
|
|
|
|
- (void)testBTST_D0D1_10 {
|
|
[self performBTSTD0D1:10];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
}
|
|
|
|
- (void)testBTST_D0D1_49 {
|
|
[self performBTSTD0D1:49];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
}
|
|
|
|
- (void)performBTSTD1Ind:(uint32_t)d1 {
|
|
_machine->set_program({
|
|
0x0310 // BTST D1, (A0)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.address[0] = 0x3000;
|
|
state.data[1] = d1;
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], d1);
|
|
XCTAssertEqual(state.address[0], 0x3000);
|
|
XCTAssertEqual(8, _machine->get_cycle_count());
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7800);
|
|
}
|
|
|
|
- (void)testBTST_D1Ind_50 {
|
|
[self performBTSTD1Ind:50];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
}
|
|
|
|
- (void)testBTST_D1Ind_3 {
|
|
[self performBTSTD1Ind:3];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
}
|
|
|
|
- (void)performBTSTImm:(uint16_t)immediate {
|
|
_machine->set_program({
|
|
0x0800, immediate // BTST #, D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345678);
|
|
XCTAssertEqual(10, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testBTST_Imm_28 {
|
|
[self performBTSTImm:28];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
}
|
|
|
|
- (void)testBTST_Imm_2 {
|
|
[self performBTSTImm:2];
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
}
|
|
|
|
- (void)testBTST_ImmWWWx {
|
|
_machine->set_program({
|
|
0x0838, 0x0006, 0x3000 // BTST #6, ($3000).W
|
|
});
|
|
*_machine->ram_at(0x3000) = 0x7800;
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(_machine->get_cycle_count(), 16);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x7800);
|
|
}
|
|
|
|
// MARK: -
|
|
// MARK: ANDI
|
|
|
|
- (void)testANDIb {
|
|
_machine->set_program({
|
|
0x0201, 0x0012 // ANDI.B #$12, D1
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.data[1] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], 0x12345610);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(8, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDIl {
|
|
_machine->set_program({
|
|
0x02b8, 0xffff, 0x0000, 0x3000 // ANDI.L #$ffff0000, ($3000).W
|
|
});
|
|
|
|
*_machine->ram_at(0x3000) = 0x0000;
|
|
*_machine->ram_at(0x3002) = 0xffff;
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x0000);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0x0000);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
|
|
XCTAssertEqual(32, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: ANDI CCR
|
|
|
|
- (void)testANDICCR {
|
|
_machine->set_program({
|
|
0x023c, 0x001b // ANDI.b #$1b, CCR
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.status |= 0xc;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0xc & 0x1b);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: ANDI SR
|
|
|
|
- (void)testANDISR_supervisor {
|
|
_machine->set_program({
|
|
0x027c, 0x0700 // ANDI.W #$700, SR
|
|
});
|
|
_machine->set_initial_stack_pointer(300);
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.program_counter, 0x1004 + 4);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testANDISR_user {
|
|
_machine->set_program({
|
|
0x46fc, 0x0000, // MOVE 0, SR
|
|
0x027c, 0x0700 // ANDI.W #$700, SR
|
|
});
|
|
|
|
_machine->run_for_instructions(2);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertNotEqual(state.program_counter, 0x1008 + 4);
|
|
// XCTAssertEqual(34, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: EOR
|
|
|
|
- (void)testEORw {
|
|
_machine->set_program({
|
|
0xb744 // EOR.w D3, D4
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.status |= Flag::Extend | Flag::Carry | Flag::Overflow;
|
|
state.data[3] = 0x54ff0056;
|
|
state.data[4] = 0x9853abcd;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54ff0056);
|
|
XCTAssertEqual(state.data[4], 0x9853ab9b);
|
|
XCTAssertEqual(4, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testEORl {
|
|
_machine->set_program({
|
|
0xb792 // EOR.l D3, (A2)
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.address[2] = 0x3000;
|
|
state.data[3] = 0x54ff0056;
|
|
*_machine->ram_at(0x3000) = 0x0f0f;
|
|
*_machine->ram_at(0x3002) = 0x0f11;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54ff0056);
|
|
XCTAssertEqual(state.address[2], 0x3000);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x5bf0);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0x0f47);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: EORI
|
|
|
|
- (void)testEORIb {
|
|
_machine->set_program({
|
|
0x0a01, 0x0012 // EORI.B #$12, D1
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.data[1] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], 0x1234566a);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(8, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testEORIl {
|
|
_machine->set_program({
|
|
0x0ab8, 0xffff, 0x0000, 0x3000 // EORI.L #$ffff0000, ($3000).W
|
|
});
|
|
|
|
*_machine->ram_at(0x3000) = 0x0000;
|
|
*_machine->ram_at(0x3002) = 0xffff;
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0xffff);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xffff);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative);
|
|
XCTAssertEqual(32, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: EORI to CCR
|
|
|
|
- (void)testEORICCR {
|
|
_machine->set_program({
|
|
0x0a3c, 0x001b // EORI.b #$1b, CCR
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.status |= 0xc;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0xc ^ 0x1b);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: EORI to SR
|
|
|
|
- (void)testEORISR_supervisor {
|
|
_machine->set_program({
|
|
0x0a7c, 0x0700 // EORI.W #$700, SR
|
|
});
|
|
_machine->set_initial_stack_pointer(300);
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.program_counter, 0x1004 + 4);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testEORISR_user {
|
|
_machine->set_program({
|
|
0x46fc, 0x0000, // MOVE 0, SR
|
|
0x0a7c, 0x0700 // EORI.W #$700, SR
|
|
});
|
|
|
|
_machine->run_for_instructions(2);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertNotEqual(state.program_counter, 0x1008 + 4);
|
|
// XCTAssertEqual(34, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: NOT
|
|
|
|
- (void)testNOTb {
|
|
_machine->set_program({
|
|
0x4600 // NOT.B D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x12345687);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative);
|
|
XCTAssertEqual(4, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testNOTw {
|
|
_machine->set_program({
|
|
0x4640 // NOT.w D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0x12340000;
|
|
state.status |= Flag::ConditionCodes;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x1234ffff);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative | Flag::Extend);
|
|
XCTAssertEqual(4, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testNOTl_Dn {
|
|
_machine->set_program({
|
|
0x4680 // NOT.l D0
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = 0xffffff00;
|
|
state.status |= Flag::ConditionCodes;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[0], 0x000000ff);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend);
|
|
XCTAssertEqual(6, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testNOTl_XXXl {
|
|
_machine->set_program({
|
|
0x46b9, 0x0000, 0x3000 // NOT.L ($3000).L
|
|
});
|
|
*_machine->ram_at(0x3000) = 0xf001;
|
|
*_machine->ram_at(0x3002) = 0x2311;
|
|
auto state = _machine->get_processor_state();
|
|
state.status |= Flag::Extend;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x0ffe);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xdcee);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend);
|
|
XCTAssertEqual(28, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: OR
|
|
|
|
- (void)testORb {
|
|
_machine->set_program({
|
|
0x8604 // OR.b D4, D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54ff0056;
|
|
state.data[4] = 0x9853abcd;
|
|
state.status |= Flag::Extend | Flag::Carry | Flag::Overflow;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54ff00df);
|
|
XCTAssertEqual(state.data[4], 0x9853abcd);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Negative);
|
|
XCTAssertEqual(4, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testORl_toDn {
|
|
_machine->set_program({
|
|
0x86ac, 0xfffa // OR.l -6(A4), D3
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3006;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x56fffb76);
|
|
XCTAssertEqual(state.address[4], 0x3006);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x1253);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb34);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(18, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testORl_fromDn {
|
|
_machine->set_program({
|
|
0x87ac, 0xfffa // OR.l D3, -6(A4)
|
|
});
|
|
auto state = _machine->get_processor_state();
|
|
state.data[3] = 0x54fff856;
|
|
state.address[4] = 0x3006;
|
|
*_machine->ram_at(0x3000) = 0x1253;
|
|
*_machine->ram_at(0x3002) = 0xfb34;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[3], 0x54fff856);
|
|
XCTAssertEqual(state.address[4], 0x3006);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x56ff);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xfb76);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(24, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: ORI
|
|
|
|
- (void)testORIb {
|
|
_machine->set_program({
|
|
0x0001, 0x0012 // ORI.B #$12, D1
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.data[1] = 0x12345678;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.data[1], 0x1234567a);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
|
|
XCTAssertEqual(8, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testORIl {
|
|
_machine->set_program({
|
|
0x00b8, 0xffff, 0x0000, 0x3000 // ORI.L #$ffff0000, ($3000).W
|
|
});
|
|
|
|
*_machine->ram_at(0x3000) = 0x0000;
|
|
*_machine->ram_at(0x3002) = 0xffff;
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0xffff);
|
|
XCTAssertEqual(*_machine->ram_at(0x3002), 0xffff);
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative);
|
|
XCTAssertEqual(32, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: ORI to CCR
|
|
|
|
- (void)testORICCR {
|
|
_machine->set_program({
|
|
0x003c, 0x001b // ORI.b #$1b, CCR
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.status |= 0xc;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, 0xc | 0x1b);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: ORI to SR
|
|
|
|
- (void)testORISR_supervisor {
|
|
_machine->set_program({
|
|
0x007c, 0x0700 // ORI.W #$700, SR
|
|
});
|
|
_machine->set_initial_stack_pointer(300);
|
|
|
|
_machine->run_for_instructions(1);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.program_counter, 0x1004 + 4);
|
|
XCTAssertEqual(20, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testORISR_user {
|
|
_machine->set_program({
|
|
0x46fc, 0x0000, // MOVE 0, SR
|
|
0x007c, 0x0700 // ORI.W #$700, SR
|
|
});
|
|
|
|
_machine->run_for_instructions(2);
|
|
|
|
const auto state = _machine->get_processor_state();
|
|
XCTAssertNotEqual(state.program_counter, 0x1008 + 4);
|
|
// XCTAssertEqual(34, _machine->get_cycle_count());
|
|
}
|
|
|
|
// MARK: TAS
|
|
|
|
- (void)performTASDnd0:(uint32_t)d0 expectedCCR:(uint16_t)ccr {
|
|
_machine->set_program({
|
|
0x4ac0 // TAS D0
|
|
});
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.data[0] = d0;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, ccr);
|
|
XCTAssertEqual(4, _machine->get_cycle_count());
|
|
}
|
|
|
|
- (void)testTAS_Dn_unset {
|
|
[self performTASDnd0:0x12345678 expectedCCR:0];
|
|
}
|
|
|
|
- (void)testTAS_Dn_set {
|
|
[self performTASDnd0:0x123456f0 expectedCCR:Flag::Negative];
|
|
}
|
|
|
|
- (void)testTAS_XXXl {
|
|
_machine->set_program({
|
|
0x4af9, 0x0000, 0x3000 // TAS ($3000).l
|
|
});
|
|
*_machine->ram_at(0x3000) = 0x1100;
|
|
|
|
auto state = _machine->get_processor_state();
|
|
state.status |= Flag::ConditionCodes;
|
|
|
|
_machine->set_processor_state(state);
|
|
_machine->run_for_instructions(1);
|
|
|
|
state = _machine->get_processor_state();
|
|
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend);
|
|
XCTAssertEqual(*_machine->ram_at(0x3000), 0x9100);
|
|
XCTAssertEqual(22, _machine->get_cycle_count());
|
|
}
|
|
|
|
@end
|