mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 18:30:21 +00:00
Merge pull request #154 from TomHarte/Memptr
Introduces a subset of necessary test cases for the Z80 memptr register, and corrects implementation to match
This commit is contained in:
commit
25fd95044c
@ -13,6 +13,8 @@
|
||||
#include <typeinfo>
|
||||
#include <cstdio>
|
||||
|
||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||
|
||||
namespace MOS {
|
||||
|
||||
/*!
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||
|
||||
namespace MOS {
|
||||
|
||||
/*!
|
||||
|
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */; };
|
||||
4B049CDD1DA3C82F00322067 /* BCDTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B049CDC1DA3C82F00322067 /* BCDTest.swift */; };
|
||||
4B08A2751EE35D56008B7065 /* Z80InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */; };
|
||||
4B08A2781EE39306008B7065 /* TestMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2771EE39306008B7065 /* TestMachine.mm */; };
|
||||
@ -456,6 +457,7 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = "<group>"; };
|
||||
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = "<group>"; };
|
||||
4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = "<group>"; };
|
||||
4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80InterruptTests.swift; sourceTree = "<group>"; };
|
||||
@ -1882,6 +1884,7 @@
|
||||
4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */,
|
||||
4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */,
|
||||
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */,
|
||||
4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */,
|
||||
4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */,
|
||||
4B3BA0C41D318B44005DD7A7 /* Bridges */,
|
||||
4B1414631B588A1100E04248 /* Test Binaries */,
|
||||
@ -2720,6 +2723,7 @@
|
||||
4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */,
|
||||
4BFCA1201ECBDC1500AC40C1 /* Z80AllRAM.cpp in Sources */,
|
||||
4BB73EB71B587A5100552FC2 /* AllSuiteATests.swift in Sources */,
|
||||
4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */,
|
||||
4B121F9B1E06293F00BFDA12 /* PCMSegmentEventSourceTests.mm in Sources */,
|
||||
4BEF6AAC1D35D1C400E73575 /* DPLLTests.swift in Sources */,
|
||||
4B3BA0CF1D318B44005DD7A7 /* MOS6522Bridge.mm in Sources */,
|
||||
|
@ -42,7 +42,8 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) {
|
||||
CSTestMachineZ80RegisterHLDash,
|
||||
CSTestMachineZ80RegisterIX, CSTestMachineZ80RegisterIY,
|
||||
CSTestMachineZ80RegisterI, CSTestMachineZ80RegisterR,
|
||||
CSTestMachineZ80RegisterIFF1, CSTestMachineZ80RegisterIFF2, CSTestMachineZ80RegisterIM
|
||||
CSTestMachineZ80RegisterIFF1, CSTestMachineZ80RegisterIFF2, CSTestMachineZ80RegisterIM,
|
||||
CSTestMachineZ80RegisterMemPtr
|
||||
};
|
||||
|
||||
@interface CSTestMachineZ80 : CSTestMachine
|
||||
|
@ -65,6 +65,8 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
||||
|
||||
case CSTestMachineZ80RegisterProgramCounter: return CPU::Z80::Register::ProgramCounter;
|
||||
case CSTestMachineZ80RegisterStackPointer: return CPU::Z80::Register::StackPointer;
|
||||
|
||||
case CSTestMachineZ80RegisterMemPtr: return CPU::Z80::Register::MemPtr;
|
||||
}
|
||||
}
|
||||
|
||||
|
348
OSBindings/Mac/Clock SignalTests/Z80MemptrTests.swift
Normal file
348
OSBindings/Mac/Clock SignalTests/Z80MemptrTests.swift
Normal file
@ -0,0 +1,348 @@
|
||||
//
|
||||
// Z80MemptrTests.swift
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 21/07/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class Z80MemptrTests: XCTestCase {
|
||||
private let machine = CSTestMachineZ80()
|
||||
|
||||
private func test(program : [UInt8], length : Int32, initialValue : UInt16) -> UInt16 {
|
||||
// Create a machine and install the supplied program at address 0, setting the PC to run from there
|
||||
machine.setValue(0x0000, for: .programCounter)
|
||||
machine.setData(Data(bytes: program), atAddress: 0x0000)
|
||||
|
||||
// Set the initial value of memptr, run for the requested number of cycles,
|
||||
// return the new value
|
||||
machine.setValue(initialValue, for: .memPtr)
|
||||
machine.runForNumber(ofCycles: length)
|
||||
return machine.value(for: .memPtr)
|
||||
}
|
||||
|
||||
// LD A, (addr)
|
||||
func testLDAnn() {
|
||||
// MEMPTR = addr+1
|
||||
var program: [UInt8] = [
|
||||
0x3a, 0x00, 0x00
|
||||
]
|
||||
for addr in 0 ..< 65536 {
|
||||
program[1] = UInt8(addr & 0x00ff)
|
||||
program[2] = UInt8(addr >> 8)
|
||||
let expectedResult = UInt16((addr + 1) & 0xffff)
|
||||
|
||||
let result = test(program: program, length: 13, initialValue: 0xffff)
|
||||
XCTAssertEqual(result, expectedResult)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
LD (addr),A
|
||||
MEMPTR_low = (addr + 1) & #FF, MEMPTR_hi = A
|
||||
Note for *BM1: MEMPTR_low = (addr + 1) & #FF, MEMPTR_hi = 0
|
||||
*/
|
||||
|
||||
// LD A, (rp)
|
||||
func testLDArp() {
|
||||
// MEMPTR = rp+1
|
||||
let bcProgram: [UInt8] = [
|
||||
0x0a
|
||||
]
|
||||
let deProgram: [UInt8] = [
|
||||
0x1a
|
||||
]
|
||||
for addr in 0 ..< 65536 {
|
||||
machine.setValue(UInt16(addr), for: .BC)
|
||||
machine.setValue(UInt16(addr), for: .DE)
|
||||
|
||||
let expectedResult = UInt16((addr + 1) & 0xffff)
|
||||
|
||||
let bcResult = test(program: bcProgram, length: 7, initialValue: 0xffff)
|
||||
let deResult = test(program: deProgram, length: 7, initialValue: 0xffff)
|
||||
|
||||
XCTAssertEqual(bcResult, expectedResult)
|
||||
XCTAssertEqual(deResult, expectedResult)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
LD (rp),A where rp -- BC or DE
|
||||
MEMPTR_low = (rp + 1) & #FF, MEMPTR_hi = A
|
||||
Note for *BM1: MEMPTR_low = (rp + 1) & #FF, MEMPTR_hi = 0
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
LD (addr), rp
|
||||
MEMPTR = addr + 1
|
||||
*/
|
||||
|
||||
// LD rp, (addr)
|
||||
func testLDnnrp() {
|
||||
// MEMPTR = addr+1
|
||||
var hlBaseProgram: [UInt8] = [
|
||||
0x22, 0x00, 0x00
|
||||
]
|
||||
|
||||
var bcEDProgram: [UInt8] = [
|
||||
0xed, 0x43, 0x00, 0x00
|
||||
]
|
||||
var deEDProgram: [UInt8] = [
|
||||
0xed, 0x53, 0x00, 0x00
|
||||
]
|
||||
var hlEDProgram: [UInt8] = [
|
||||
0xed, 0x63, 0x00, 0x00
|
||||
]
|
||||
var spEDProgram: [UInt8] = [
|
||||
0xed, 0x73, 0x00, 0x00
|
||||
]
|
||||
|
||||
var ixProgram: [UInt8] = [
|
||||
0xdd, 0x22, 0x00, 0x00
|
||||
]
|
||||
var iyProgram: [UInt8] = [
|
||||
0xfd, 0x22, 0x00, 0x00
|
||||
]
|
||||
|
||||
for addr in 0 ..< 65536 {
|
||||
hlBaseProgram[1] = UInt8(addr & 0x00ff)
|
||||
hlBaseProgram[2] = UInt8(addr >> 8)
|
||||
|
||||
bcEDProgram[2] = UInt8(addr & 0x00ff)
|
||||
bcEDProgram[3] = UInt8(addr >> 8)
|
||||
deEDProgram[2] = UInt8(addr & 0x00ff)
|
||||
deEDProgram[3] = UInt8(addr >> 8)
|
||||
hlEDProgram[2] = UInt8(addr & 0x00ff)
|
||||
hlEDProgram[3] = UInt8(addr >> 8)
|
||||
spEDProgram[2] = UInt8(addr & 0x00ff)
|
||||
spEDProgram[3] = UInt8(addr >> 8)
|
||||
|
||||
ixProgram[2] = UInt8(addr & 0x00ff)
|
||||
ixProgram[3] = UInt8(addr >> 8)
|
||||
iyProgram[2] = UInt8(addr & 0x00ff)
|
||||
iyProgram[3] = UInt8(addr >> 8)
|
||||
|
||||
let expectedResult = UInt16((addr + 1) & 0xffff)
|
||||
|
||||
XCTAssertEqual(test(program: hlBaseProgram, length: 16, initialValue: 0xffff), expectedResult)
|
||||
|
||||
XCTAssertEqual(test(program: bcEDProgram, length: 20, initialValue: 0xffff), expectedResult)
|
||||
XCTAssertEqual(test(program: deEDProgram, length: 20, initialValue: 0xffff), expectedResult)
|
||||
XCTAssertEqual(test(program: hlEDProgram, length: 20, initialValue: 0xffff), expectedResult)
|
||||
XCTAssertEqual(test(program: spEDProgram, length: 20, initialValue: 0xffff), expectedResult)
|
||||
|
||||
XCTAssertEqual(test(program: ixProgram, length: 20, initialValue: 0xffff), expectedResult)
|
||||
XCTAssertEqual(test(program: iyProgram, length: 20, initialValue: 0xffff), expectedResult)
|
||||
}
|
||||
}
|
||||
|
||||
// EX (SP), rp
|
||||
func testEXSPrp() {
|
||||
// MEMPTR = rp at end
|
||||
var hlProgram: [UInt8] = [
|
||||
0xe3, 0x00, 0x00, 0x00
|
||||
]
|
||||
var ixProgram: [UInt8] = [
|
||||
0xdd, 0xe3, 0x00, 0x00
|
||||
]
|
||||
var iyProgram: [UInt8] = [
|
||||
0xfd, 0xe3, 0x00, 0x00
|
||||
]
|
||||
|
||||
machine.setValue(2, for: .stackPointer)
|
||||
|
||||
for addr in 0 ..< 65536 {
|
||||
hlProgram[2] = UInt8(addr & 0x00ff)
|
||||
hlProgram[3] = UInt8(addr >> 8)
|
||||
ixProgram[2] = UInt8(addr & 0x00ff)
|
||||
ixProgram[3] = UInt8(addr >> 8)
|
||||
iyProgram[2] = UInt8(addr & 0x00ff)
|
||||
iyProgram[3] = UInt8(addr >> 8)
|
||||
|
||||
XCTAssertEqual(test(program: hlProgram, length: 19, initialValue: 0xffff), UInt16(addr))
|
||||
XCTAssertEqual(test(program: ixProgram, length: 23, initialValue: 0xffff), UInt16(addr))
|
||||
XCTAssertEqual(test(program: iyProgram, length: 23, initialValue: 0xffff), UInt16(addr))
|
||||
}
|
||||
}
|
||||
|
||||
// ADD/ADC/SBC dest, src
|
||||
func testADDADCSBCrr() {
|
||||
// MEMPTR = dest prior to modification + 1
|
||||
let addProgram: [UInt8] = [
|
||||
0x09
|
||||
]
|
||||
let adcProgram: [UInt8] = [
|
||||
0xed, 0x4a
|
||||
]
|
||||
let sbcProgram: [UInt8] = [
|
||||
0xed, 0x42
|
||||
]
|
||||
|
||||
for addr in 0 ..< 65536 {
|
||||
let expectedResult = UInt16((addr + 1) & 0xffff)
|
||||
machine.setValue(UInt16(addr), for: .HL)
|
||||
|
||||
XCTAssertEqual(test(program: addProgram, length: 11, initialValue: 0xffff), expectedResult)
|
||||
XCTAssertEqual(test(program: adcProgram, length: 15, initialValue: 0xffff), expectedResult)
|
||||
XCTAssertEqual(test(program: sbcProgram, length: 15, initialValue: 0xffff), expectedResult)
|
||||
}
|
||||
}
|
||||
|
||||
// RLD/RRD
|
||||
func testRLDRRD() {
|
||||
// MEMPTR = HL + 1
|
||||
let rldProgram: [UInt8] = [
|
||||
0xed, 0x6f
|
||||
]
|
||||
let rrdProgram: [UInt8] = [
|
||||
0xed, 0x67
|
||||
]
|
||||
|
||||
for addr in 0 ..< 65536 {
|
||||
let expectedResult = UInt16((addr + 1) & 0xffff)
|
||||
machine.setValue(UInt16(addr), for: .HL)
|
||||
|
||||
XCTAssertEqual(test(program: rldProgram, length: 18, initialValue: 0xffff), expectedResult)
|
||||
XCTAssertEqual(test(program: rrdProgram, length: 18, initialValue: 0xffff), expectedResult)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
JR/DJNZ/RET/RETI/RST (jumping to addr)
|
||||
MEMPTR = addr
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
JP(except JP rp)/CALL addr (even in case of conditional call/jp, independantly on condition satisfied or not)
|
||||
MEMPTR = addr
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
IN A,(port)
|
||||
MEMPTR = (A_before_operation << 8) + port + 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
IN A,(C)
|
||||
MEMPTR = BC + 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
OUT (port),A
|
||||
MEMPTR_low = (port + 1) & #FF, MEMPTR_hi = A
|
||||
Note for *BM1: MEMPTR_low = (port + 1) & #FF, MEMPTR_hi = 0
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
OUT (C),A
|
||||
MEMPTR = BC + 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
LDIR/LDDR
|
||||
when BC == 1: MEMPTR is not changed
|
||||
when BC <> 1: MEMPTR = PC + 1, where PC = instruction address
|
||||
*/
|
||||
|
||||
// CPI
|
||||
func testCPI() {
|
||||
// MEMPTR = MEMPTR + 1
|
||||
let program: [UInt8] = [
|
||||
0xed, 0xa1
|
||||
]
|
||||
machine.setData(Data(bytes: program), atAddress: 0x0000)
|
||||
machine.setValue(0, for: .memPtr)
|
||||
|
||||
for c in 1 ..< 65536 {
|
||||
machine.setValue(0x0000, for: .programCounter)
|
||||
machine.runForNumber(ofCycles: 16)
|
||||
XCTAssertEqual(UInt16(c), machine.value(for: .memPtr))
|
||||
}
|
||||
}
|
||||
|
||||
// CPD
|
||||
func testCPD() {
|
||||
// MEMPTR = MEMPTR - 1
|
||||
let program: [UInt8] = [
|
||||
0xed, 0xa9
|
||||
]
|
||||
machine.setData(Data(bytes: program), atAddress: 0x0000)
|
||||
machine.setValue(0, for: .memPtr)
|
||||
|
||||
for c in 1 ..< 65536 {
|
||||
machine.setValue(0x0000, for: .programCounter)
|
||||
machine.runForNumber(ofCycles: 16)
|
||||
XCTAssertEqual(UInt16(65536 - c), machine.value(for: .memPtr))
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
CPIR
|
||||
when BC=1 or A=(HL): exactly as CPI
|
||||
In other cases MEMPTR = PC + 1 on each step, where PC = instruction address.
|
||||
Note* since at the last execution BC=1 or A=(HL), resulting MEMPTR = PC + 1 + 1
|
||||
(if there were not interrupts during the execution)
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
CPDR
|
||||
when BC=1 or A=(HL): exactly as CPD
|
||||
In other cases MEMPTR = PC + 1 on each step, where PC = instruction address.
|
||||
Note* since at the last execution BC=1 or A=(HL), resulting MEMPTR = PC + 1 - 1
|
||||
(if there were not interrupts during the execution)
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
INI
|
||||
MEMPTR = BC_before_decrementing_B + 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
IND
|
||||
MEMPTR = BC_before_decrementing_B - 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
INIR
|
||||
exactly as INI on each execution.
|
||||
I.e. resulting MEMPTR = ((1 << 8) + C) + 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
INDR
|
||||
exactly as IND on each execution.
|
||||
I.e. resulting MEMPTR = ((1 << 8) + C) - 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
OUTI
|
||||
MEMPTR = BC_after_decrementing_B + 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
OUTD
|
||||
MEMPTR = BC_after_decrementing_B - 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
OTIR
|
||||
exactly as OUTI on each execution. I.e. resulting MEMPTR = C + 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
OTDR
|
||||
exactly as OUTD on each execution. I.e. resulting MEMPTR = C - 1
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
Any instruction with (INDEX+d):
|
||||
MEMPTR = INDEX+d
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
Interrupt call to addr:
|
||||
As usual CALL. I.e. MEMPTR = addr
|
||||
*/
|
||||
}
|
@ -41,7 +41,9 @@ enum Register {
|
||||
IYh, IYl, IY,
|
||||
R, I, Refresh,
|
||||
|
||||
IFF1, IFF2, IM
|
||||
IFF1, IFF2, IM,
|
||||
|
||||
MemPtr
|
||||
};
|
||||
|
||||
/*
|
||||
@ -463,7 +465,7 @@ template <class T> class Processor {
|
||||
NOP_ROW(), /* 0x20 */
|
||||
NOP_ROW(), /* 0x30 */
|
||||
/* 0x40 IN B, (C); 0x41 OUT (C), B */ IN_OUT(bc_.bytes.high),
|
||||
/* 0x42 SBC HL, BC */ SBC16(hl_, bc_), /* 0x43 LD (nn), BC */ StdInstr(Read16Inc(pc_, temp16_), Write16(temp16_, bc_)),
|
||||
/* 0x42 SBC HL, BC */ SBC16(hl_, bc_), /* 0x43 LD (nn), BC */ StdInstr(Read16Inc(pc_, memptr_), Write16(memptr_, bc_)),
|
||||
/* 0x44 NEG */ StdInstr({MicroOp::NEG}), /* 0x45 RETN */ StdInstr(Pop(pc_), {MicroOp::RETN}),
|
||||
/* 0x46 IM 0 */ StdInstr({MicroOp::IM}), /* 0x47 LD I, A */ Instr(6, {MicroOp::Move8, &a_, &ir_.bytes.high}),
|
||||
/* 0x40 IN B, (C); 0x41 OUT (C), B */ IN_OUT(bc_.bytes.low),
|
||||
@ -471,7 +473,7 @@ template <class T> class Processor {
|
||||
/* 0x4c NEG */ StdInstr({MicroOp::NEG}), /* 0x4d RETI */ StdInstr(Pop(pc_), {MicroOp::RETN}),
|
||||
/* 0x4e IM 0/1 */ StdInstr({MicroOp::IM}), /* 0x4f LD R, A */ Instr(6, {MicroOp::Move8, &a_, &ir_.bytes.low}),
|
||||
/* 0x40 IN B, (C); 0x41 OUT (C), B */ IN_OUT(de_.bytes.high),
|
||||
/* 0x52 SBC HL, DE */ SBC16(hl_, de_), /* 0x53 LD (nn), DE */ StdInstr(Read16Inc(pc_, temp16_), Write16(temp16_, de_)),
|
||||
/* 0x52 SBC HL, DE */ SBC16(hl_, de_), /* 0x53 LD (nn), DE */ StdInstr(Read16Inc(pc_, memptr_), Write16(memptr_, de_)),
|
||||
/* 0x54 NEG */ StdInstr({MicroOp::NEG}), /* 0x55 RETN */ StdInstr(Pop(pc_), {MicroOp::RETN}),
|
||||
/* 0x56 IM 1 */ StdInstr({MicroOp::IM}), /* 0x57 LD A, I */ Instr(6, {MicroOp::Move8, &ir_.bytes.high, &a_}, {MicroOp::SetAFlags}),
|
||||
/* 0x40 IN B, (C); 0x41 OUT (C), B */ IN_OUT(de_.bytes.low),
|
||||
@ -479,7 +481,7 @@ template <class T> class Processor {
|
||||
/* 0x5c NEG */ StdInstr({MicroOp::NEG}), /* 0x5d RETN */ StdInstr(Pop(pc_), {MicroOp::RETN}),
|
||||
/* 0x5e IM 2 */ StdInstr({MicroOp::IM}), /* 0x5f LD A, R */ Instr(6, {MicroOp::Move8, &ir_.bytes.low, &a_}, {MicroOp::SetAFlags}),
|
||||
/* 0x40 IN B, (C); 0x41 OUT (C), B */ IN_OUT(hl_.bytes.high),
|
||||
/* 0x62 SBC HL, HL */ SBC16(hl_, hl_), /* 0x63 LD (nn), HL */ StdInstr(Read16Inc(pc_, temp16_), Write16(temp16_, hl_)),
|
||||
/* 0x62 SBC HL, HL */ SBC16(hl_, hl_), /* 0x63 LD (nn), HL */ StdInstr(Read16Inc(pc_, memptr_), Write16(memptr_, hl_)),
|
||||
/* 0x64 NEG */ StdInstr({MicroOp::NEG}), /* 0x65 RETN */ StdInstr(Pop(pc_), {MicroOp::RETN}),
|
||||
/* 0x66 IM 0 */ StdInstr({MicroOp::IM}), /* 0x67 RRD */ StdInstr(Read3(hl_, temp8_), InternalOperation(8), {MicroOp::RRD}, Write3(hl_, temp8_)),
|
||||
/* 0x40 IN B, (C); 0x41 OUT (C), B */ IN_OUT(hl_.bytes.low),
|
||||
@ -487,7 +489,7 @@ template <class T> class Processor {
|
||||
/* 0x6c NEG */ StdInstr({MicroOp::NEG}), /* 0x6d RETN */ StdInstr(Pop(pc_), {MicroOp::RETN}),
|
||||
/* 0x6e IM 0/1 */ StdInstr({MicroOp::IM}), /* 0x6f RLD */ StdInstr(Read3(hl_, temp8_), InternalOperation(8), {MicroOp::RLD}, Write3(hl_, temp8_)),
|
||||
/* 0x70 IN (C) */ IN_C(temp8_), /* 0x71 OUT (C), 0 */ StdInstr({MicroOp::SetZero}, Output(bc_, temp8_)),
|
||||
/* 0x72 SBC HL, SP */ SBC16(hl_, sp_), /* 0x73 LD (nn), SP */ StdInstr(Read16Inc(pc_, temp16_), Write16(temp16_, sp_)),
|
||||
/* 0x72 SBC HL, SP */ SBC16(hl_, sp_), /* 0x73 LD (nn), SP */ StdInstr(Read16Inc(pc_, memptr_), Write16(memptr_, sp_)),
|
||||
/* 0x74 NEG */ StdInstr({MicroOp::NEG}), /* 0x75 RETN */ StdInstr(Pop(pc_), {MicroOp::RETN}),
|
||||
/* 0x76 IM 1 */ StdInstr({MicroOp::IM}), /* 0x77 XX */ NOP,
|
||||
/* 0x40 IN B, (C); 0x41 OUT (C), B */ IN_OUT(a_),
|
||||
@ -573,7 +575,7 @@ template <class T> class Processor {
|
||||
|
||||
/* 0x07 RLCA */ StdInstr({MicroOp::RLCA}),
|
||||
/* 0x08 EX AF, AF' */ StdInstr({MicroOp::ExAFAFDash}), /* 0x09 ADD HL, BC */ ADD16(index, bc_),
|
||||
/* 0x0a LD A, (BC) */ StdInstr({MicroOp::Move16, &bc_.full, &memptr_.full}, Read3(memptr_, a_)),
|
||||
/* 0x0a LD A, (BC) */ StdInstr({MicroOp::Move16, &bc_.full, &memptr_.full}, Read3(memptr_, a_), Inc16(memptr_)),
|
||||
|
||||
/* 0x0b DEC BC; 0x0c INC C; 0x0d DEC C; 0x0e LD C, n */
|
||||
DEC_INC_DEC_LD(bc_, bc_.bytes.low),
|
||||
@ -589,14 +591,14 @@ template <class T> class Processor {
|
||||
/* 0x17 RLA */ StdInstr({MicroOp::RLA}),
|
||||
/* 0x18 JR */ StdInstr(ReadInc(pc_, temp8_), InternalOperation(10), {MicroOp::CalculateIndexAddress, &pc_.full}, {MicroOp::Move16, &memptr_.full, &pc_.full}),
|
||||
/* 0x19 ADD HL, DE */ ADD16(index, de_),
|
||||
/* 0x1a LD A, (DE) */ StdInstr({MicroOp::Move16, &de_.full, &memptr_.full}, Read3(memptr_, a_)),
|
||||
/* 0x1a LD A, (DE) */ StdInstr({MicroOp::Move16, &de_.full, &memptr_.full}, Read3(memptr_, a_), Inc16(memptr_)),
|
||||
|
||||
/* 0x1b DEC DE; 0x1c INC E; 0x1d DEC E; 0x1e LD E, n */
|
||||
DEC_INC_DEC_LD(de_, de_.bytes.low),
|
||||
|
||||
/* 0x1f RRA */ StdInstr({MicroOp::RRA}),
|
||||
/* 0x20 JR NZ */ JR(TestNZ), /* 0x21 LD HL, nn */ StdInstr(Read16Inc(pc_, index)),
|
||||
/* 0x22 LD (nn), HL */ StdInstr(Read16Inc(pc_, temp16_), Write16(temp16_, index)),
|
||||
/* 0x22 LD (nn), HL */ StdInstr(Read16Inc(pc_, memptr_), Write16(memptr_, index)),
|
||||
|
||||
/* 0x23 INC HL; 0x24 INC H; 0x25 DEC H; 0x26 LD H, n */
|
||||
INC_INC_DEC_LD(index, index.bytes.high),
|
||||
@ -618,7 +620,7 @@ template <class T> class Processor {
|
||||
/* 0x37 SCF */ StdInstr({MicroOp::SCF}),
|
||||
/* 0x38 JR C */ JR(TestC),
|
||||
/* 0x39 ADD HL, SP */ ADD16(index, sp_),
|
||||
/* 0x3a LD A, (nn) */ StdInstr(Read16Inc(pc_, memptr_), Read3(memptr_, a_)),
|
||||
/* 0x3a LD A, (nn) */ StdInstr(Read16Inc(pc_, memptr_), Read3(memptr_, a_), Inc16(memptr_)),
|
||||
/* 0x3b DEC SP */ Instr(8, {MicroOp::Decrement16, &sp_.full}),
|
||||
|
||||
/* 0x3c INC A; 0x3d DEC A; 0x3e LD A, n */
|
||||
@ -1196,9 +1198,9 @@ template <class T> class Processor {
|
||||
#pragma mark - 16-bit arithmetic
|
||||
|
||||
case MicroOp::ADD16: {
|
||||
memptr_.full = *(uint16_t *)operation->source;
|
||||
uint16_t sourceValue = memptr_.full;
|
||||
uint16_t destinationValue = *(uint16_t *)operation->destination;
|
||||
memptr_.full = *(uint16_t *)operation->destination;
|
||||
uint16_t sourceValue = *(uint16_t *)operation->source;
|
||||
uint16_t destinationValue = memptr_.full;
|
||||
int result = sourceValue + destinationValue;
|
||||
int halfResult = (sourceValue&0xfff) + (destinationValue&0xfff);
|
||||
|
||||
@ -1208,12 +1210,13 @@ template <class T> class Processor {
|
||||
subtract_flag_ = 0;
|
||||
|
||||
*(uint16_t *)operation->destination = (uint16_t)result;
|
||||
memptr_.full++;
|
||||
} break;
|
||||
|
||||
case MicroOp::ADC16: {
|
||||
memptr_.full = *(uint16_t *)operation->source;
|
||||
uint16_t sourceValue = memptr_.full;
|
||||
uint16_t destinationValue = *(uint16_t *)operation->destination;
|
||||
memptr_.full = *(uint16_t *)operation->destination;
|
||||
uint16_t sourceValue = *(uint16_t *)operation->source;
|
||||
uint16_t destinationValue = memptr_.full;
|
||||
int result = sourceValue + destinationValue + (carry_result_ & Flag::Carry);
|
||||
int halfResult = (sourceValue&0xfff) + (destinationValue&0xfff) + (carry_result_ & Flag::Carry);
|
||||
|
||||
@ -1228,12 +1231,13 @@ template <class T> class Processor {
|
||||
parity_overflow_result_ = (uint8_t)(overflow >> 13);
|
||||
|
||||
*(uint16_t *)operation->destination = (uint16_t)result;
|
||||
memptr_.full++;
|
||||
} break;
|
||||
|
||||
case MicroOp::SBC16: {
|
||||
memptr_.full = *(uint16_t *)operation->source;
|
||||
uint16_t sourceValue = memptr_.full;
|
||||
uint16_t destinationValue = *(uint16_t *)operation->destination;
|
||||
memptr_.full = *(uint16_t *)operation->destination;
|
||||
uint16_t sourceValue = *(uint16_t *)operation->source;
|
||||
uint16_t destinationValue = memptr_.full;
|
||||
int result = destinationValue - sourceValue - (carry_result_ & Flag::Carry);
|
||||
int halfResult = (destinationValue&0xfff) - (sourceValue&0xfff) - (carry_result_ & Flag::Carry);
|
||||
|
||||
@ -1251,6 +1255,7 @@ template <class T> class Processor {
|
||||
parity_overflow_result_ = (uint8_t)(overflow >> 13);
|
||||
|
||||
*(uint16_t *)operation->destination = (uint16_t)result;
|
||||
memptr_.full++;
|
||||
} break;
|
||||
|
||||
#pragma mark - Conditionals
|
||||
@ -1796,6 +1801,8 @@ template <class T> class Processor {
|
||||
case Register::IFF2: return iff2_ ? 1 : 0;
|
||||
case Register::IM: return (uint16_t)interrupt_mode_;
|
||||
|
||||
case Register::MemPtr: return memptr_.full;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@ -1855,6 +1862,8 @@ template <class T> class Processor {
|
||||
case Register::IFF2: iff2_ = !!value; break;
|
||||
case Register::IM: interrupt_mode_ = value % 3; break;
|
||||
|
||||
case Register::MemPtr: memptr_.full = value; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user